Commit 4f66d166 by yanglang123

commit

parent d4d077ae
/*
* Eslint config file
* Documentation: https://eslint.org/docs/user-guide/configuring/
* Install the Eslint extension before using this feature.
*/
module.exports = {
env: {
es6: true,
browser: true,
node: true,
},
ecmaFeatures: {
modules: true,
},
parserOptions: {
ecmaVersion: 2018,
sourceType: 'module',
},
globals: {
wx: true,
App: true,
Page: true,
getCurrentPages: true,
getApp: true,
Component: true,
requirePlugin: true,
requireMiniProgram: true,
},
// extends: 'eslint:recommended',
rules: {},
}
# Windows
[Dd]esktop.ini
Thumbs.db
$RECYCLE.BIN/
# macOS
.DS_Store
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
# Node.js
node_modules/
// app.js
App({
onLaunch() {
// 展示本地存储能力
const logs = wx.getStorageSync('logs') || []
logs.unshift(Date.now())
wx.setStorageSync('logs', logs)
// 登录
wx.login({
success: res => {
// 发送 res.code 到后台换取 openId, sessionKey, unionId
}
})
},
globalData: {
userInfo: null
}
})
{
"pages": [
"pages/login/index",
"pages/home/index",
"pages/activity/index",
"pages/activity/activyDetail/index",
"pages/searchInfo/index",
"pages/mine/index",
"pages/NewsMessage/index",
"pages/changePsd/index",
"pages/h5Link/index",
"pages/mine/myLeaveMessage/index",
"pages/mine/messageBox/index",
"pages/mine/myAppeal/index",
"pages/mine/myAppeal/detail/index",
"pages/mine/myComment/index",
"pages/mine/myContribute/index",
"pages/mine/myintegral/index",
"pages/mine/myCollection/index",
"pages/mine/browsingHistory/index",
"pages/mine/userInfo/index",
"pages/mine/aboutZhdj/index",
"pages/NewsMessage/news/index",
"pages/workTask/index",
"pages/allDescribe/index",
"pages/questionnaire/index",
"pages/vote/index",
"pages/vote/theCharts/index",
"pages/vote/detail/index",
"pages/contribute/index",
"pages/trainingAndTest/index",
"pages/trainingAndTest/examDetail/index",
"pages/trainingAndTest/examHistory/index",
"pages/trainingAndTest/examQuestion/index",
"pages/trainingAndTest/examResult/index"
],
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#E35B45",
"borderStyle": "black",
"backgroundColor": "#F8F8F8",
"list": [{
"pagePath": "pages/home/index",
"iconPath": "static/home.png",
"selectedIconPath": "static/home-active.png",
"text": "首页"
},
{
"pagePath": "pages/activity/index",
"iconPath": "static/activity.png",
"selectedIconPath": "static/activity-active.png",
"text": "日历"
},
{
"pagePath": "pages/mine/index",
"iconPath": "static/mine.png",
"selectedIconPath": "static/mine-active.png",
"text": "我的"
}
]
},
"window": {
"navigationBarTextStyle": "white",
"navigationBarTitleText": "机电e先锋 v1.0.3",
"navigationBarBackgroundColor": "#D23A29"
},
"style": "v2",
"componentFramework": "glass-easel",
"sitemapLocation": "sitemap.json",
"lazyCodeLoading": "requiredComponents"
}
/**app.wxss**/
.container {
height: 100%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-between;
padding: 200rpx 0;
box-sizing: border-box;
}
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921828, function(require, module, exports) {
var charenc = {
// UTF-8 encoding
utf8: {
// Convert a string to a byte array
stringToBytes: function(str) {
return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));
},
// Convert a byte array to a string
bytesToString: function(bytes) {
return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));
}
},
// Binary encoding
bin: {
// Convert a string to a byte array
stringToBytes: function(str) {
for (var bytes = [], i = 0; i < str.length; i++)
bytes.push(str.charCodeAt(i) & 0xFF);
return bytes;
},
// Convert a byte array to a string
bytesToString: function(bytes) {
for (var str = [], i = 0; i < bytes.length; i++)
str.push(String.fromCharCode(bytes[i]));
return str.join('');
}
}
};
module.exports = charenc;
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921828);
})()
//miniprogram-npm-outsideDeps=[]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["charenc.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["var charenc = {\n // UTF-8 encoding\n utf8: {\n // Convert a string to a byte array\n stringToBytes: function(str) {\n return charenc.bin.stringToBytes(unescape(encodeURIComponent(str)));\n },\n\n // Convert a byte array to a string\n bytesToString: function(bytes) {\n return decodeURIComponent(escape(charenc.bin.bytesToString(bytes)));\n }\n },\n\n // Binary encoding\n bin: {\n // Convert a string to a byte array\n stringToBytes: function(str) {\n for (var bytes = [], i = 0; i < str.length; i++)\n bytes.push(str.charCodeAt(i) & 0xFF);\n return bytes;\n },\n\n // Convert a byte array to a string\n bytesToString: function(bytes) {\n for (var str = [], i = 0; i < bytes.length; i++)\n str.push(String.fromCharCode(bytes[i]));\n return str.join('');\n }\n }\n};\n\nmodule.exports = charenc;\n"]}
\ No newline at end of file
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921829, function(require, module, exports) {
const { base64ToBit, checkDate } = require('./utils');
const { getSolarTerm } = require('./solar_term');
const table = [];
const heavenlyStemStr = '甲乙丙丁戊己庚辛壬癸';
const earthlyBranchStr = '子丑寅卯辰巳午未申酉戌亥';
const zodiacStr = '鼠牛虎兔龙蛇马羊猴鸡狗猪';
const lunarMonthStr = '正二三四五六七八九十冬腊';
const nubmerStr = '一二三四五六七八九十';
function decompressData() {
const base64Str = 'hLaCVwUrqpNDSYNlUaqgrUE1pJXQSuak2FJoaSrqlC1QNailtBK26TcElwpLWyWDUoNqJW1ArYJVySXgkuzJYNSg6lVtSC1oFbHJuCS58loZKhqU20oLVQVqSq2BLoSWlkrCpV7SoNlBaqqrUE2gpbNSuClcVKg6VBqpq1QVaglslK4KVwUmPpMGyrrVQVqCW1UroJWhSamk0NJY1ShaoFtTS2glbBJtKS4Ul1ZLBqUG1GraBVsEq6pLwSXBks2pQdSw1lBawKtlk2hJcGSyalQ1KDaUlqoK1PVbAl0JLVyVhUqFpSWqgrVlVqCXQUtspXBSsKk0dKg1UFapJtQS2alcFJwaTL0mDVMFqja1BLbaV0ErQpNbSWGkoapLtUC1oFbSStgk29JcKSwqlW1KDaQVtGq2CTeEl4JLgyWzUoOpQaqSrYFVwSXHkuDJZ9SoalBtKq1UFagptRS6ClsVKwqVC0prVQVqgq0lLoKWwUrOpODSbuUwaqCtVU2oJbBSuik4NFo6TBqkG1TNagVtBK5KToUWhoqWyUNUg';
const bitStr = base64ToBit(base64Str);
let solarDate = { y: 1900, m: 1, d: 31, obj: new Date(1900, 0, 31, 0, 0, 0, 0) };
let heavenlyStem = 6; // 天干
let earthlyBranch = 0; // 地支
for (let i = 0; i < bitStr.length; ) {
if (i + 16 >= bitStr.length) {
break;
}
const head = bitStr.substr(i, 4);
i += 4;
const leapMonth = +`0b${head}`;
const monthCount = leapMonth > 0 ? 13 : 12;
const months = bitStr.substr(i, monthCount).split('').map(o => +o);
i += monthCount;
table.push({
solarDate,
leapMonth,
months,
heavenlyStem,
earthlyBranch
});
const dateCount = monthCount*29 + months.filter(o => o == 1).length;
const newSolarDate = new Date(solarDate.y, solarDate.m - 1, solarDate.d + dateCount, 0, 0, 0, 0);
solarDate = {
y: newSolarDate.getFullYear(),
m: newSolarDate.getMonth() + 1,
d: newSolarDate.getDate(),
obj: newSolarDate
};
heavenlyStem = (heavenlyStem + 1) % 10;
earthlyBranch = (earthlyBranch + 1) % 12;
}
}
decompressData();
function isBefore(base, target) {
if (base.y != target.y) {
return base.y > target.y;
} else if (base.m != target.m) {
return base.m > target.m;
} else if (base.d != target.d) {
return base.d > target.d;
}
return false;
}
function getLunarStr(month, date, isLeap) {
const monthStr = `${isLeap ? '闰' : ''}${lunarMonthStr[month - 1]}月`;
if (date <= 10) {
return `${monthStr}${nubmerStr[date - 1]}`;
} else if (date < 20) {
return `${monthStr}${nubmerStr[date - 11]}`;
} else if (date == 20) {
return `${monthStr}廿十`;
} else if (date > 20) {
return `${monthStr}廿${nubmerStr[date - 21]}`;
} else {
return `${monthStr}三十`;
}
}
function getLunar(year, month, date) {
year = Math.floor(+year);
month = Math.floor(+month);
date = Math.floor(+date);
checkDate(year, month, date);
let index = year - 1900;
let row = table[index];
if (isBefore(row.solarDate, { y: year, m: month, d: date })) {
index -= 1;
row = table[index];
}
if (!row) {
throw new Error('Invalid Date');
}
const targetDate = new Date(year, month - 1, date, 0, 0, 0, 0);
let delta = Math.round((targetDate.getTime() - row.solarDate.obj.getTime()) / (24*60*60*1000));
let afterLeap = false;
for(let i = 0; i < row.months.length; i++) {
const isLeap = row.leapMonth > 0 && i == row.leapMonth;
if (isLeap) {
afterLeap = true;
}
const days = 29 + row.months[i];
if (delta < days) {
let lunarMonth = afterLeap ? i : i + 1;
return {
lunarMonth,
lunarDate: delta + 1,
isLeap,
solarTerm: getSolarTerm(year, month, date),
lunarYear: `${heavenlyStemStr[row.heavenlyStem]}${earthlyBranchStr[row.earthlyBranch]}年`,
zodiac: `${zodiacStr[row.earthlyBranch]}`,
dateStr: getLunarStr(lunarMonth, delta + 1, isLeap)
};
} else {
delta -= days;
}
}
throw new Error(`There's something wrong!`);
}
module.exports = { getLunar };
}, function(modId) {var map = {"./utils":1743039921830,"./solar_term":1743039921831}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921830, function(require, module, exports) {
function base64ToBit(base64Str) {
const base64CodeMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';
const result = [];
for (let i = 0; i < base64Str.length; i++) {
let n = base64CodeMap.indexOf(base64Str[i]);
result.push(n.toString(2).padStart(6, '0'));
}
return result.join('');
}
function checkDate(year, month, date) {
if (year < 1901 || year > 2100) {
throw new Error('Invalid Year');
}
if (month < 1 || month > 12) {
throw new Error('Invalid Month');
}
if (date < 1 || date > 31) {
throw new Error('Invalid Date');
}
if ([4, 6, 9, 11].indexOf(month) != -1 && date > 30) {
throw new Error('Invalid Date');
}
if (month == 2) {
if (date > 29) {
throw new Error('Invalid Date');
} else {
let isLeap = false;
if (year % 400 == 0) {
isLeap = true
} else if (year % 4 == 0 && year % 100 != 0) {
isLeap = true;
}
if (!isLeap && date > 28) {
throw new Error('Invalid Date');
}
}
}
}
module.exports = {
base64ToBit,
checkDate,
};
}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921831, function(require, module, exports) {
const { base64ToBit, checkDate } = require('./utils');
// 2bit代表日期 共48bit
// 48bit -> base64 8个
// 200年一共68种情况
const names = ['小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨', '立夏', '小满', '芒种',
'夏至', '小暑', '大暑', '立秋', '处暑', '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪', '冬至'];
const baseDate = [4, 19, 3, 18, 4, 19, 4, 19, 4, 20, 4, 20, 6, 22, 6, 22, 6, 22, 7, 22, 6, 21, 6, 21];
const table = [];
function decompressData() {
const codeStr = 'ABCDAECDAECDFGHIJKHILKMILABNOABNOAENOAENOAEPQRGSTUGSTLAVTOAWXOAWXOAYXOAYZOabcdebcQUfgThijkOilXOimXOimXOimcOnocdpqcQrsgktujkvumXvumXvumcvumcvwocxyqcz0sj10s213u243um43um53wm56wq567q589s+/0s~/3u~!3u@#3um';
const groupsStr = 'paaqmqqpqaquqqqqqvruruqq6qWaWZqlqaqqqqqqlaaqmqqppaaqqqqqqrququqqqqWaWZaVlaaampqlpaaqqqqplaWampqlqaququqqqqWZWZVVlaWaWZqlqqVZWZVVlaWaWZaVlaaqmpqpqmVZVZVVVaWaWZaVlaWampqpqlVZVZVVqVVZVVVVVaWZWZVVqVVVVVVVVaVZWZVVpaaqmpqpqVFVVVVVVaVZVZVVlaWaWZalpaaampqppVFVRVVVVWVZVZVVlaWaWpqlpVFVRVVUVVVZVVVVVaWZWZaVVFVZVVVVVFVVVVVVpVFVRUVUVFFVVVVVpVFFRUVUVFFVRVVVlVBFRUVUUFFVRVVVlVBFBEVUUFFVRVVUlVBFBEVQUFFFRUVUlVBFBEFQUFBFRUVUlVBEBEFAQFBFBEVUVVBEBEFAVVVVVVVVQFBFBEVQVVBEBEAAVVAEAEAAQFBFBEFQUFBFBUVUQFBEBEFAUFBFBEVUVQAEAAAAAFBEBEFAVQAAAAAAAFBEBEAAVAAAAAAAAFBEAEAA';
const groups = [];
for (let i = 0; i < groupsStr.length; i += 8) {
const groupBitStr = base64ToBit(groupsStr.substr(i, 8));
const group = [];
for (let j = 0; j < groupBitStr.length; j += 2) {
group.push(+`0b${groupBitStr.substr(j, 2)}`);
}
groups.push(group);
}
const codeMapStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/~!@#';
for (let i = 0; i < codeStr.length; i++) {
table.push(groups[codeMapStr.indexOf(codeStr[i])]);
}
}
decompressData();
function getSolarTerm(year, month, date) {
year = Math.floor(+year);
month = Math.floor(+month);
date = Math.floor(+date);
checkDate(year, month, date);
const index = (month - 1) * 2 + (date < 15 ? 0 : 1);
const d = baseDate[index] + table[year - 1901][index];
if (date == d) {
return names[index];
} else {
return null;
}
}
module.exports = { getSolarTerm };
}, function(modId) { var map = {"./utils":1743039921830}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921829);
})()
//miniprogram-npm-outsideDeps=[]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["lunar_calendar.js","utils.js","solar_term.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA,ACHA;ADIA,ACHA;ADIA,ACHA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA,ADGA;ADIA,AENA;AFOA,AENA;AFOA,AENA;AFOA,AENA;AFOA,AENA;AFOA,AENA;AFOA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["const { base64ToBit, checkDate } = require('./utils');\nconst { getSolarTerm } = require('./solar_term');\n\nconst table = [];\nconst heavenlyStemStr = '甲乙丙丁戊己庚辛壬癸';\nconst earthlyBranchStr = '子丑寅卯辰巳午未申酉戌亥';\nconst zodiacStr = '鼠牛虎兔龙蛇马羊猴鸡狗猪';\nconst lunarMonthStr = '正二三四五六七八九十冬腊';\nconst nubmerStr = '一二三四五六七八九十';\n\nfunction decompressData() {\n const base64Str = 'hLaCVwUrqpNDSYNlUaqgrUE1pJXQSuak2FJoaSrqlC1QNailtBK26TcElwpLWyWDUoNqJW1ArYJVySXgkuzJYNSg6lVtSC1oFbHJuCS58loZKhqU20oLVQVqSq2BLoSWlkrCpV7SoNlBaqqrUE2gpbNSuClcVKg6VBqpq1QVaglslK4KVwUmPpMGyrrVQVqCW1UroJWhSamk0NJY1ShaoFtTS2glbBJtKS4Ul1ZLBqUG1GraBVsEq6pLwSXBks2pQdSw1lBawKtlk2hJcGSyalQ1KDaUlqoK1PVbAl0JLVyVhUqFpSWqgrVlVqCXQUtspXBSsKk0dKg1UFapJtQS2alcFJwaTL0mDVMFqja1BLbaV0ErQpNbSWGkoapLtUC1oFbSStgk29JcKSwqlW1KDaQVtGq2CTeEl4JLgyWzUoOpQaqSrYFVwSXHkuDJZ9SoalBtKq1UFagptRS6ClsVKwqVC0prVQVqgq0lLoKWwUrOpODSbuUwaqCtVU2oJbBSuik4NFo6TBqkG1TNagVtBK5KToUWhoqWyUNUg';\n const bitStr = base64ToBit(base64Str);\n let solarDate = { y: 1900, m: 1, d: 31, obj: new Date(1900, 0, 31, 0, 0, 0, 0) };\n let heavenlyStem = 6; // 天干\n let earthlyBranch = 0; // 地支\n for (let i = 0; i < bitStr.length; ) {\n if (i + 16 >= bitStr.length) {\n break;\n }\n const head = bitStr.substr(i, 4);\n i += 4;\n const leapMonth = +`0b${head}`;\n const monthCount = leapMonth > 0 ? 13 : 12;\n const months = bitStr.substr(i, monthCount).split('').map(o => +o);\n i += monthCount;\n\n table.push({\n solarDate,\n leapMonth,\n months,\n heavenlyStem,\n earthlyBranch\n });\n\n const dateCount = monthCount*29 + months.filter(o => o == 1).length;\n const newSolarDate = new Date(solarDate.y, solarDate.m - 1, solarDate.d + dateCount, 0, 0, 0, 0);\n solarDate = {\n y: newSolarDate.getFullYear(),\n m: newSolarDate.getMonth() + 1,\n d: newSolarDate.getDate(),\n obj: newSolarDate\n };\n heavenlyStem = (heavenlyStem + 1) % 10;\n earthlyBranch = (earthlyBranch + 1) % 12;\n }\n}\n\ndecompressData();\n\nfunction isBefore(base, target) {\n if (base.y != target.y) {\n return base.y > target.y;\n } else if (base.m != target.m) {\n return base.m > target.m;\n } else if (base.d != target.d) {\n return base.d > target.d;\n }\n return false;\n}\n\nfunction getLunarStr(month, date, isLeap) {\n const monthStr = `${isLeap ? '闰' : ''}${lunarMonthStr[month - 1]}月`;\n if (date <= 10) {\n return `${monthStr}初${nubmerStr[date - 1]}`;\n } else if (date < 20) {\n return `${monthStr}十${nubmerStr[date - 11]}`;\n } else if (date == 20) {\n return `${monthStr}廿十`;\n } else if (date > 20) {\n return `${monthStr}廿${nubmerStr[date - 21]}`;\n } else {\n return `${monthStr}三十`;\n }\n}\n\nfunction getLunar(year, month, date) {\n year = Math.floor(+year);\n month = Math.floor(+month);\n date = Math.floor(+date);\n checkDate(year, month, date);\n let index = year - 1900;\n let row = table[index];\n if (isBefore(row.solarDate, { y: year, m: month, d: date })) {\n index -= 1;\n row = table[index];\n }\n if (!row) {\n throw new Error('Invalid Date');\n }\n const targetDate = new Date(year, month - 1, date, 0, 0, 0, 0);\n let delta = Math.round((targetDate.getTime() - row.solarDate.obj.getTime()) / (24*60*60*1000));\n let afterLeap = false;\n for(let i = 0; i < row.months.length; i++) {\n const isLeap = row.leapMonth > 0 && i == row.leapMonth;\n if (isLeap) {\n afterLeap = true;\n }\n const days = 29 + row.months[i];\n if (delta < days) {\n let lunarMonth = afterLeap ? i : i + 1;\n return {\n lunarMonth,\n lunarDate: delta + 1,\n isLeap,\n solarTerm: getSolarTerm(year, month, date),\n lunarYear: `${heavenlyStemStr[row.heavenlyStem]}${earthlyBranchStr[row.earthlyBranch]}年`,\n zodiac: `${zodiacStr[row.earthlyBranch]}`,\n dateStr: getLunarStr(lunarMonth, delta + 1, isLeap)\n };\n } else {\n delta -= days;\n }\n }\n throw new Error(`There's something wrong!`);\n}\n\nmodule.exports = { getLunar };\n","function base64ToBit(base64Str) {\n const base64CodeMap = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/';\n const result = [];\n for (let i = 0; i < base64Str.length; i++) {\n let n = base64CodeMap.indexOf(base64Str[i]);\n result.push(n.toString(2).padStart(6, '0'));\n }\n return result.join('');\n}\n\nfunction checkDate(year, month, date) {\n if (year < 1901 || year > 2100) {\n throw new Error('Invalid Year');\n }\n if (month < 1 || month > 12) {\n throw new Error('Invalid Month');\n }\n if (date < 1 || date > 31) {\n throw new Error('Invalid Date');\n }\n if ([4, 6, 9, 11].indexOf(month) != -1 && date > 30) {\n throw new Error('Invalid Date');\n }\n if (month == 2) {\n if (date > 29) {\n throw new Error('Invalid Date');\n } else {\n let isLeap = false;\n if (year % 400 == 0) {\n isLeap = true\n } else if (year % 4 == 0 && year % 100 != 0) {\n isLeap = true;\n }\n if (!isLeap && date > 28) {\n throw new Error('Invalid Date');\n }\n }\n }\n}\n\nmodule.exports = {\n base64ToBit,\n checkDate,\n};","const { base64ToBit, checkDate } = require('./utils');\n\n// 2bit代表日期 共48bit\n// 48bit -> base64 8个\n// 200年一共68种情况\nconst names = ['小寒', '大寒', '立春', '雨水', '惊蛰', '春分', '清明', '谷雨', '立夏', '小满', '芒种',\n '夏至', '小暑', '大暑', '立秋', '处暑', '白露', '秋分', '寒露', '霜降', '立冬', '小雪', '大雪', '冬至'];\nconst baseDate = [4, 19, 3, 18, 4, 19, 4, 19, 4, 20, 4, 20, 6, 22, 6, 22, 6, 22, 7, 22, 6, 21, 6, 21];\n\nconst table = [];\n\nfunction decompressData() {\n const codeStr = 'ABCDAECDAECDFGHIJKHILKMILABNOABNOAENOAENOAEPQRGSTUGSTLAVTOAWXOAWXOAYXOAYZOabcdebcQUfgThijkOilXOimXOimXOimcOnocdpqcQrsgktujkvumXvumXvumcvumcvwocxyqcz0sj10s213u243um43um53wm56wq567q589s+/0s~/3u~!3u@#3um';\n const groupsStr = 'paaqmqqpqaquqqqqqvruruqq6qWaWZqlqaqqqqqqlaaqmqqppaaqqqqqqrququqqqqWaWZaVlaaampqlpaaqqqqplaWampqlqaququqqqqWZWZVVlaWaWZqlqqVZWZVVlaWaWZaVlaaqmpqpqmVZVZVVVaWaWZaVlaWampqpqlVZVZVVqVVZVVVVVaWZWZVVqVVVVVVVVaVZWZVVpaaqmpqpqVFVVVVVVaVZVZVVlaWaWZalpaaampqppVFVRVVVVWVZVZVVlaWaWpqlpVFVRVVUVVVZVVVVVaWZWZaVVFVZVVVVVFVVVVVVpVFVRUVUVFFVVVVVpVFFRUVUVFFVRVVVlVBFRUVUUFFVRVVVlVBFBEVUUFFVRVVUlVBFBEVQUFFFRUVUlVBFBEFQUFBFRUVUlVBEBEFAQFBFBEVUVVBEBEFAVVVVVVVVQFBFBEVQVVBEBEAAVVAEAEAAQFBFBEFQUFBFBUVUQFBEBEFAUFBFBEVUVQAEAAAAAFBEBEFAVQAAAAAAAFBEBEAAVAAAAAAAAFBEAEAA';\n const groups = [];\n for (let i = 0; i < groupsStr.length; i += 8) {\n const groupBitStr = base64ToBit(groupsStr.substr(i, 8));\n const group = [];\n for (let j = 0; j < groupBitStr.length; j += 2) {\n group.push(+`0b${groupBitStr.substr(j, 2)}`);\n }\n groups.push(group);\n }\n const codeMapStr = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/~!@#';\n for (let i = 0; i < codeStr.length; i++) {\n table.push(groups[codeMapStr.indexOf(codeStr[i])]);\n }\n}\n\ndecompressData();\n\nfunction getSolarTerm(year, month, date) {\n year = Math.floor(+year);\n month = Math.floor(+month);\n date = Math.floor(+date);\n checkDate(year, month, date);\n const index = (month - 1) * 2 + (date < 15 ? 0 : 1);\n const d = baseDate[index] + table[year - 1901][index];\n if (date == d) {\n return names[index];\n } else {\n return null;\n }\n}\n\nmodule.exports = { getSolarTerm };\n"]}
\ No newline at end of file
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921832, function(require, module, exports) {
(function() {
var base64map
= 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',
crypt = {
// Bit-wise rotation left
rotl: function(n, b) {
return (n << b) | (n >>> (32 - b));
},
// Bit-wise rotation right
rotr: function(n, b) {
return (n << (32 - b)) | (n >>> b);
},
// Swap big-endian to little-endian and vice versa
endian: function(n) {
// If number given, swap endian
if (n.constructor == Number) {
return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;
}
// Else, assume array and swap all items
for (var i = 0; i < n.length; i++)
n[i] = crypt.endian(n[i]);
return n;
},
// Generate an array of any length of random bytes
randomBytes: function(n) {
for (var bytes = []; n > 0; n--)
bytes.push(Math.floor(Math.random() * 256));
return bytes;
},
// Convert a byte array to big-endian 32-bit words
bytesToWords: function(bytes) {
for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)
words[b >>> 5] |= bytes[i] << (24 - b % 32);
return words;
},
// Convert big-endian 32-bit words to a byte array
wordsToBytes: function(words) {
for (var bytes = [], b = 0; b < words.length * 32; b += 8)
bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);
return bytes;
},
// Convert a byte array to a hex string
bytesToHex: function(bytes) {
for (var hex = [], i = 0; i < bytes.length; i++) {
hex.push((bytes[i] >>> 4).toString(16));
hex.push((bytes[i] & 0xF).toString(16));
}
return hex.join('');
},
// Convert a hex string to a byte array
hexToBytes: function(hex) {
for (var bytes = [], c = 0; c < hex.length; c += 2)
bytes.push(parseInt(hex.substr(c, 2), 16));
return bytes;
},
// Convert a byte array to a base-64 string
bytesToBase64: function(bytes) {
for (var base64 = [], i = 0; i < bytes.length; i += 3) {
var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
for (var j = 0; j < 4; j++)
if (i * 8 + j * 6 <= bytes.length * 8)
base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));
else
base64.push('=');
}
return base64.join('');
},
// Convert a base-64 string to a byte array
base64ToBytes: function(base64) {
// Remove non-base-64 characters
base64 = base64.replace(/[^A-Z0-9+\/]/ig, '');
for (var bytes = [], i = 0, imod4 = 0; i < base64.length;
imod4 = ++i % 4) {
if (imod4 == 0) continue;
bytes.push(((base64map.indexOf(base64.charAt(i - 1))
& (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))
| (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));
}
return bytes;
}
};
module.exports = crypt;
})();
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921832);
})()
//miniprogram-npm-outsideDeps=[]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["crypt.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["(function() {\n var base64map\n = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/',\n\n crypt = {\n // Bit-wise rotation left\n rotl: function(n, b) {\n return (n << b) | (n >>> (32 - b));\n },\n\n // Bit-wise rotation right\n rotr: function(n, b) {\n return (n << (32 - b)) | (n >>> b);\n },\n\n // Swap big-endian to little-endian and vice versa\n endian: function(n) {\n // If number given, swap endian\n if (n.constructor == Number) {\n return crypt.rotl(n, 8) & 0x00FF00FF | crypt.rotl(n, 24) & 0xFF00FF00;\n }\n\n // Else, assume array and swap all items\n for (var i = 0; i < n.length; i++)\n n[i] = crypt.endian(n[i]);\n return n;\n },\n\n // Generate an array of any length of random bytes\n randomBytes: function(n) {\n for (var bytes = []; n > 0; n--)\n bytes.push(Math.floor(Math.random() * 256));\n return bytes;\n },\n\n // Convert a byte array to big-endian 32-bit words\n bytesToWords: function(bytes) {\n for (var words = [], i = 0, b = 0; i < bytes.length; i++, b += 8)\n words[b >>> 5] |= bytes[i] << (24 - b % 32);\n return words;\n },\n\n // Convert big-endian 32-bit words to a byte array\n wordsToBytes: function(words) {\n for (var bytes = [], b = 0; b < words.length * 32; b += 8)\n bytes.push((words[b >>> 5] >>> (24 - b % 32)) & 0xFF);\n return bytes;\n },\n\n // Convert a byte array to a hex string\n bytesToHex: function(bytes) {\n for (var hex = [], i = 0; i < bytes.length; i++) {\n hex.push((bytes[i] >>> 4).toString(16));\n hex.push((bytes[i] & 0xF).toString(16));\n }\n return hex.join('');\n },\n\n // Convert a hex string to a byte array\n hexToBytes: function(hex) {\n for (var bytes = [], c = 0; c < hex.length; c += 2)\n bytes.push(parseInt(hex.substr(c, 2), 16));\n return bytes;\n },\n\n // Convert a byte array to a base-64 string\n bytesToBase64: function(bytes) {\n for (var base64 = [], i = 0; i < bytes.length; i += 3) {\n var triplet = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];\n for (var j = 0; j < 4; j++)\n if (i * 8 + j * 6 <= bytes.length * 8)\n base64.push(base64map.charAt((triplet >>> 6 * (3 - j)) & 0x3F));\n else\n base64.push('=');\n }\n return base64.join('');\n },\n\n // Convert a base-64 string to a byte array\n base64ToBytes: function(base64) {\n // Remove non-base-64 characters\n base64 = base64.replace(/[^A-Z0-9+\\/]/ig, '');\n\n for (var bytes = [], i = 0, imod4 = 0; i < base64.length;\n imod4 = ++i % 4) {\n if (imod4 == 0) continue;\n bytes.push(((base64map.indexOf(base64.charAt(i - 1))\n & (Math.pow(2, -2 * imod4 + 8) - 1)) << (imod4 * 2))\n | (base64map.indexOf(base64.charAt(i)) >>> (6 - imod4 * 2)));\n }\n return bytes;\n }\n };\n\n module.exports = crypt;\n})();\n"]}
\ No newline at end of file
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921833, function(require, module, exports) {
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t="undefined"!=typeof globalThis?globalThis:t||self).dayjs=e()}(this,(function(){var t=1e3,e=6e4,n=36e5,r="millisecond",i="second",s="minute",u="hour",a="day",o="week",c="month",f="quarter",h="year",d="date",l="Invalid Date",$=/^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[Tt\s]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?[.:]?(\d+)?$/,y=/\[([^\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:"en",weekdays:"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),months:"January_February_March_April_May_June_July_August_September_October_November_December".split("_"),ordinal:function(t){var e=["th","st","nd","rd"],n=t%100;return"["+t+(e[(n-20)%10]||e[n]||e[0])+"]"}},m=function(t,e,n){var r=String(t);return!r||r.length>=e?t:""+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?"+":"-")+m(r,2,"0")+":"+m(i,2,"0")},m:function t(e,n){if(e.date()<n.date())return-t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,c),s=n-i<0,u=e.clone().add(r+(s?-1:1),c);return+(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return{M:c,y:h,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:f}[t]||String(t||"").toLowerCase().replace(/s$/,"")},u:function(t){return void 0===t}},g="en",D={};D[g]=M;var p="$isDayjsObject",S=function(t){return t instanceof _||!(!t||!t[p])},w=function t(e,n,r){var i;if(!e)return g;if("string"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split("-");if(!i&&u.length>1)return t(u[0])}else{var a=e.name;D[a]=e,i=a}return!r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n="object"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[p]=!0}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if("string"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||"0").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return b},m.isValid=function(){return!(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<O(t)},m.$g=function(t,e,n){return b.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!b.u(e)||e,f=b.p(t),l=function(t,e){var i=b.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},$=function(t,e){return b.w(n.toDate()[t].apply(n.toDate("s"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,v="set"+(this.$u?"UTC":"");switch(f){case h:return r?l(1,0):l(31,11);case c:return r?l(1,M):l(0,M+1);case o:var g=this.$locale().weekStart||0,D=(y<g?y+7:y)-g;return l(r?m-D:m+(6-D),M);case a:case d:return $(v+"Hours",0);case u:return $(v+"Minutes",1);case s:return $(v+"Seconds",2);case i:return $(v+"Milliseconds",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,!1)},m.$set=function(t,e){var n,o=b.p(t),f="set"+(this.$u?"UTC":""),l=(n={},n[a]=f+"Date",n[d]=f+"Date",n[c]=f+"Month",n[h]=f+"FullYear",n[u]=f+"Hours",n[s]=f+"Minutes",n[i]=f+"Seconds",n[r]=f+"Milliseconds",n)[o],$=o===a?this.$D+(e-this.$W):e;if(o===c||o===h){var y=this.clone().set(d,1);y.$d[l]($),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d}else l&&this.$d[l]($);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[b.p(t)]()},m.add=function(r,f){var d,l=this;r=Number(r);var $=b.p(f),y=function(t){var e=O(l);return b.w(e.date(e.date()+Math.round(t*r)),l)};if($===c)return this.set(c,this.$M+r);if($===h)return this.set(h,this.$y+r);if($===a)return y(1);if($===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[$]||1,m=this.$d.getTime()+r*M;return b.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||l;var r=t||"YYYY-MM-DDTHH:mm:ssZ",i=b.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,c=n.months,f=n.meridiem,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},d=function(t){return b.s(s%12||12,t,"0")},$=f||function(t,e,n){var r=t<12?"AM":"PM";return n?r.toLowerCase():r};return r.replace(y,(function(t,r){return r||function(t){switch(t){case"YY":return String(e.$y).slice(-2);case"YYYY":return b.s(e.$y,4,"0");case"M":return a+1;case"MM":return b.s(a+1,2,"0");case"MMM":return h(n.monthsShort,a,c,3);case"MMMM":return h(c,a);case"D":return e.$D;case"DD":return b.s(e.$D,2,"0");case"d":return String(e.$W);case"dd":return h(n.weekdaysMin,e.$W,o,2);case"ddd":return h(n.weekdaysShort,e.$W,o,3);case"dddd":return o[e.$W];case"H":return String(s);case"HH":return b.s(s,2,"0");case"h":return d(1);case"hh":return d(2);case"a":return $(s,u,!0);case"A":return $(s,u,!1);case"m":return String(u);case"mm":return b.s(u,2,"0");case"s":return String(e.$s);case"ss":return b.s(e.$s,2,"0");case"SSS":return b.s(e.$ms,3,"0");case"Z":return i}return null}(t)||i.replace(":","")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,l){var $,y=this,M=b.p(d),m=O(r),v=(m.utcOffset()-this.utcOffset())*e,g=this-m,D=function(){return b.m(y,m)};switch(M){case h:$=D()/12;break;case c:$=D();break;case f:$=D()/3;break;case o:$=(g-v)/6048e5;break;case a:$=(g-v)/864e5;break;case u:$=g/n;break;case s:$=g/e;break;case i:$=g/t;break;default:$=g}return l?$:b.a($)},m.daysInMonth=function(){return this.endOf(c).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=w(t,e,!0);return r&&(n.$L=r),n},m.clone=function(){return b.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),k=_.prototype;return O.prototype=k,[["$ms",r],["$s",i],["$m",s],["$H",u],["$W",a],["$M",c],["$y",h],["$D",d]].forEach((function(t){k[t[1]]=function(e){return this.$g(e,t[0],t[1])}})),O.extend=function(t,e){return t.$i||(t(e,_,O),t.$i=!0),O},O.locale=w,O.isDayjs=S,O.unix=function(t){return O(1e3*t)},O.en=D[g],O.Ls=D,O.p={},O}));
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921833);
})()
//miniprogram-npm-outsideDeps=[]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["dayjs.min.js"],"names":[],"mappings":";;;;;;;AAAA","file":"index.js","sourcesContent":["!function(t,e){\"object\"==typeof exports&&\"undefined\"!=typeof module?module.exports=e():\"function\"==typeof define&&define.amd?define(e):(t=\"undefined\"!=typeof globalThis?globalThis:t||self).dayjs=e()}(this,(function(){var t=1e3,e=6e4,n=36e5,r=\"millisecond\",i=\"second\",s=\"minute\",u=\"hour\",a=\"day\",o=\"week\",c=\"month\",f=\"quarter\",h=\"year\",d=\"date\",l=\"Invalid Date\",$=/^(\\d{4})[-/]?(\\d{1,2})?[-/]?(\\d{0,2})[Tt\\s]*(\\d{1,2})?:?(\\d{1,2})?:?(\\d{1,2})?[.:]?(\\d+)?$/,y=/\\[([^\\]]+)]|Y{1,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g,M={name:\"en\",weekdays:\"Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday\".split(\"_\"),months:\"January_February_March_April_May_June_July_August_September_October_November_December\".split(\"_\"),ordinal:function(t){var e=[\"th\",\"st\",\"nd\",\"rd\"],n=t%100;return\"[\"+t+(e[(n-20)%10]||e[n]||e[0])+\"]\"}},m=function(t,e,n){var r=String(t);return!r||r.length>=e?t:\"\"+Array(e+1-r.length).join(n)+t},v={s:m,z:function(t){var e=-t.utcOffset(),n=Math.abs(e),r=Math.floor(n/60),i=n%60;return(e<=0?\"+\":\"-\")+m(r,2,\"0\")+\":\"+m(i,2,\"0\")},m:function t(e,n){if(e.date()<n.date())return-t(n,e);var r=12*(n.year()-e.year())+(n.month()-e.month()),i=e.clone().add(r,c),s=n-i<0,u=e.clone().add(r+(s?-1:1),c);return+(-(r+(n-i)/(s?i-u:u-i))||0)},a:function(t){return t<0?Math.ceil(t)||0:Math.floor(t)},p:function(t){return{M:c,y:h,w:o,d:a,D:d,h:u,m:s,s:i,ms:r,Q:f}[t]||String(t||\"\").toLowerCase().replace(/s$/,\"\")},u:function(t){return void 0===t}},g=\"en\",D={};D[g]=M;var p=\"$isDayjsObject\",S=function(t){return t instanceof _||!(!t||!t[p])},w=function t(e,n,r){var i;if(!e)return g;if(\"string\"==typeof e){var s=e.toLowerCase();D[s]&&(i=s),n&&(D[s]=n,i=s);var u=e.split(\"-\");if(!i&&u.length>1)return t(u[0])}else{var a=e.name;D[a]=e,i=a}return!r&&i&&(g=i),i||!r&&g},O=function(t,e){if(S(t))return t.clone();var n=\"object\"==typeof e?e:{};return n.date=t,n.args=arguments,new _(n)},b=v;b.l=w,b.i=S,b.w=function(t,e){return O(t,{locale:e.$L,utc:e.$u,x:e.$x,$offset:e.$offset})};var _=function(){function M(t){this.$L=w(t.locale,null,!0),this.parse(t),this.$x=this.$x||t.x||{},this[p]=!0}var m=M.prototype;return m.parse=function(t){this.$d=function(t){var e=t.date,n=t.utc;if(null===e)return new Date(NaN);if(b.u(e))return new Date;if(e instanceof Date)return new Date(e);if(\"string\"==typeof e&&!/Z$/i.test(e)){var r=e.match($);if(r){var i=r[2]-1||0,s=(r[7]||\"0\").substring(0,3);return n?new Date(Date.UTC(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)):new Date(r[1],i,r[3]||1,r[4]||0,r[5]||0,r[6]||0,s)}}return new Date(e)}(t),this.init()},m.init=function(){var t=this.$d;this.$y=t.getFullYear(),this.$M=t.getMonth(),this.$D=t.getDate(),this.$W=t.getDay(),this.$H=t.getHours(),this.$m=t.getMinutes(),this.$s=t.getSeconds(),this.$ms=t.getMilliseconds()},m.$utils=function(){return b},m.isValid=function(){return!(this.$d.toString()===l)},m.isSame=function(t,e){var n=O(t);return this.startOf(e)<=n&&n<=this.endOf(e)},m.isAfter=function(t,e){return O(t)<this.startOf(e)},m.isBefore=function(t,e){return this.endOf(e)<O(t)},m.$g=function(t,e,n){return b.u(t)?this[e]:this.set(n,t)},m.unix=function(){return Math.floor(this.valueOf()/1e3)},m.valueOf=function(){return this.$d.getTime()},m.startOf=function(t,e){var n=this,r=!!b.u(e)||e,f=b.p(t),l=function(t,e){var i=b.w(n.$u?Date.UTC(n.$y,e,t):new Date(n.$y,e,t),n);return r?i:i.endOf(a)},$=function(t,e){return b.w(n.toDate()[t].apply(n.toDate(\"s\"),(r?[0,0,0,0]:[23,59,59,999]).slice(e)),n)},y=this.$W,M=this.$M,m=this.$D,v=\"set\"+(this.$u?\"UTC\":\"\");switch(f){case h:return r?l(1,0):l(31,11);case c:return r?l(1,M):l(0,M+1);case o:var g=this.$locale().weekStart||0,D=(y<g?y+7:y)-g;return l(r?m-D:m+(6-D),M);case a:case d:return $(v+\"Hours\",0);case u:return $(v+\"Minutes\",1);case s:return $(v+\"Seconds\",2);case i:return $(v+\"Milliseconds\",3);default:return this.clone()}},m.endOf=function(t){return this.startOf(t,!1)},m.$set=function(t,e){var n,o=b.p(t),f=\"set\"+(this.$u?\"UTC\":\"\"),l=(n={},n[a]=f+\"Date\",n[d]=f+\"Date\",n[c]=f+\"Month\",n[h]=f+\"FullYear\",n[u]=f+\"Hours\",n[s]=f+\"Minutes\",n[i]=f+\"Seconds\",n[r]=f+\"Milliseconds\",n)[o],$=o===a?this.$D+(e-this.$W):e;if(o===c||o===h){var y=this.clone().set(d,1);y.$d[l]($),y.init(),this.$d=y.set(d,Math.min(this.$D,y.daysInMonth())).$d}else l&&this.$d[l]($);return this.init(),this},m.set=function(t,e){return this.clone().$set(t,e)},m.get=function(t){return this[b.p(t)]()},m.add=function(r,f){var d,l=this;r=Number(r);var $=b.p(f),y=function(t){var e=O(l);return b.w(e.date(e.date()+Math.round(t*r)),l)};if($===c)return this.set(c,this.$M+r);if($===h)return this.set(h,this.$y+r);if($===a)return y(1);if($===o)return y(7);var M=(d={},d[s]=e,d[u]=n,d[i]=t,d)[$]||1,m=this.$d.getTime()+r*M;return b.w(m,this)},m.subtract=function(t,e){return this.add(-1*t,e)},m.format=function(t){var e=this,n=this.$locale();if(!this.isValid())return n.invalidDate||l;var r=t||\"YYYY-MM-DDTHH:mm:ssZ\",i=b.z(this),s=this.$H,u=this.$m,a=this.$M,o=n.weekdays,c=n.months,f=n.meridiem,h=function(t,n,i,s){return t&&(t[n]||t(e,r))||i[n].slice(0,s)},d=function(t){return b.s(s%12||12,t,\"0\")},$=f||function(t,e,n){var r=t<12?\"AM\":\"PM\";return n?r.toLowerCase():r};return r.replace(y,(function(t,r){return r||function(t){switch(t){case\"YY\":return String(e.$y).slice(-2);case\"YYYY\":return b.s(e.$y,4,\"0\");case\"M\":return a+1;case\"MM\":return b.s(a+1,2,\"0\");case\"MMM\":return h(n.monthsShort,a,c,3);case\"MMMM\":return h(c,a);case\"D\":return e.$D;case\"DD\":return b.s(e.$D,2,\"0\");case\"d\":return String(e.$W);case\"dd\":return h(n.weekdaysMin,e.$W,o,2);case\"ddd\":return h(n.weekdaysShort,e.$W,o,3);case\"dddd\":return o[e.$W];case\"H\":return String(s);case\"HH\":return b.s(s,2,\"0\");case\"h\":return d(1);case\"hh\":return d(2);case\"a\":return $(s,u,!0);case\"A\":return $(s,u,!1);case\"m\":return String(u);case\"mm\":return b.s(u,2,\"0\");case\"s\":return String(e.$s);case\"ss\":return b.s(e.$s,2,\"0\");case\"SSS\":return b.s(e.$ms,3,\"0\");case\"Z\":return i}return null}(t)||i.replace(\":\",\"\")}))},m.utcOffset=function(){return 15*-Math.round(this.$d.getTimezoneOffset()/15)},m.diff=function(r,d,l){var $,y=this,M=b.p(d),m=O(r),v=(m.utcOffset()-this.utcOffset())*e,g=this-m,D=function(){return b.m(y,m)};switch(M){case h:$=D()/12;break;case c:$=D();break;case f:$=D()/3;break;case o:$=(g-v)/6048e5;break;case a:$=(g-v)/864e5;break;case u:$=g/n;break;case s:$=g/e;break;case i:$=g/t;break;default:$=g}return l?$:b.a($)},m.daysInMonth=function(){return this.endOf(c).$D},m.$locale=function(){return D[this.$L]},m.locale=function(t,e){if(!t)return this.$L;var n=this.clone(),r=w(t,e,!0);return r&&(n.$L=r),n},m.clone=function(){return b.w(this.$d,this)},m.toDate=function(){return new Date(this.valueOf())},m.toJSON=function(){return this.isValid()?this.toISOString():null},m.toISOString=function(){return this.$d.toISOString()},m.toString=function(){return this.$d.toUTCString()},M}(),k=_.prototype;return O.prototype=k,[[\"$ms\",r],[\"$s\",i],[\"$m\",s],[\"$H\",u],[\"$W\",a],[\"$M\",c],[\"$y\",h],[\"$D\",d]].forEach((function(t){k[t[1]]=function(e){return this.$g(e,t[0],t[1])}})),O.extend=function(t,e){return t.$i||(t(e,_,O),t.$i=!0),O},O.locale=w,O.isDayjs=S,O.unix=function(t){return O(1e3*t)},O.en=D[g],O.Ls=D,O.p={},O}));"]}
\ No newline at end of file
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921834, function(require, module, exports) {
/*!
* Determine if an object is a Buffer
*
* @author Feross Aboukhadijeh <https://feross.org>
* @license MIT
*/
// The _isBuffer check is for Safari 5-7 support, because it's missing
// Object.prototype.constructor. Remove this eventually
module.exports = function (obj) {
return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)
}
function isBuffer (obj) {
return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)
}
// For Node v0.10 support. Remove this eventually.
function isSlowBuffer (obj) {
return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))
}
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921834);
})()
//miniprogram-npm-outsideDeps=[]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["index.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["/*!\n * Determine if an object is a Buffer\n *\n * @author Feross Aboukhadijeh <https://feross.org>\n * @license MIT\n */\n\n// The _isBuffer check is for Safari 5-7 support, because it's missing\n// Object.prototype.constructor. Remove this eventually\nmodule.exports = function (obj) {\n return obj != null && (isBuffer(obj) || isSlowBuffer(obj) || !!obj._isBuffer)\n}\n\nfunction isBuffer (obj) {\n return !!obj.constructor && typeof obj.constructor.isBuffer === 'function' && obj.constructor.isBuffer(obj)\n}\n\n// For Node v0.10 support. Remove this eventually.\nfunction isSlowBuffer (obj) {\n return typeof obj.readFloatLE === 'function' && typeof obj.slice === 'function' && isBuffer(obj.slice(0, 0))\n}\n"]}
\ No newline at end of file
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921835, function(require, module, exports) {
(function(){
// Copyright (c) 2005 Tom Wu
// All Rights Reserved.
// See "LICENSE" for details.
// Basic JavaScript BN library - subset useful for RSA encryption.
// Bits per digit
var dbits;
// JavaScript engine analysis
var canary = 0xdeadbeefcafe;
var j_lm = ((canary&0xffffff)==0xefcafe);
// (public) Constructor
function BigInteger(a,b,c) {
if(a != null)
if("number" == typeof a) this.fromNumber(a,b,c);
else if(b == null && "string" != typeof a) this.fromString(a,256);
else this.fromString(a,b);
}
// return new, unset BigInteger
function nbi() { return new BigInteger(null); }
// am: Compute w_j += (x*this_i), propagate carries,
// c is initial carry, returns final carry.
// c < 3*dvalue, x < 2*dvalue, this_i < dvalue
// We need to select the fastest one that works in this environment.
// am1: use a single mult and divide to get the high bits,
// max digit bits should be 26 because
// max internal value = 2*dvalue^2-2*dvalue (< 2^53)
function am1(i,x,w,j,c,n) {
while(--n >= 0) {
var v = x*this[i++]+w[j]+c;
c = Math.floor(v/0x4000000);
w[j++] = v&0x3ffffff;
}
return c;
}
// am2 avoids a big mult-and-extract completely.
// Max digit bits should be <= 30 because we do bitwise ops
// on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)
function am2(i,x,w,j,c,n) {
var xl = x&0x7fff, xh = x>>15;
while(--n >= 0) {
var l = this[i]&0x7fff;
var h = this[i++]>>15;
var m = xh*l+h*xl;
l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);
c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);
w[j++] = l&0x3fffffff;
}
return c;
}
// Alternately, set max digit bits to 28 since some
// browsers slow down when dealing with 32-bit numbers.
function am3(i,x,w,j,c,n) {
var xl = x&0x3fff, xh = x>>14;
while(--n >= 0) {
var l = this[i]&0x3fff;
var h = this[i++]>>14;
var m = xh*l+h*xl;
l = xl*l+((m&0x3fff)<<14)+w[j]+c;
c = (l>>28)+(m>>14)+xh*h;
w[j++] = l&0xfffffff;
}
return c;
}
var inBrowser = typeof navigator !== "undefined";
if(inBrowser && j_lm && (navigator.appName == "Microsoft Internet Explorer")) {
BigInteger.prototype.am = am2;
dbits = 30;
}
else if(inBrowser && j_lm && (navigator.appName != "Netscape")) {
BigInteger.prototype.am = am1;
dbits = 26;
}
else { // Mozilla/Netscape seems to prefer am3
BigInteger.prototype.am = am3;
dbits = 28;
}
BigInteger.prototype.DB = dbits;
BigInteger.prototype.DM = ((1<<dbits)-1);
BigInteger.prototype.DV = (1<<dbits);
var BI_FP = 52;
BigInteger.prototype.FV = Math.pow(2,BI_FP);
BigInteger.prototype.F1 = BI_FP-dbits;
BigInteger.prototype.F2 = 2*dbits-BI_FP;
// Digit conversions
var BI_RM = "0123456789abcdefghijklmnopqrstuvwxyz";
var BI_RC = new Array();
var rr,vv;
rr = "0".charCodeAt(0);
for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;
rr = "a".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
rr = "A".charCodeAt(0);
for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;
function int2char(n) { return BI_RM.charAt(n); }
function intAt(s,i) {
var c = BI_RC[s.charCodeAt(i)];
return (c==null)?-1:c;
}
// (protected) copy this to r
function bnpCopyTo(r) {
for(var i = this.t-1; i >= 0; --i) r[i] = this[i];
r.t = this.t;
r.s = this.s;
}
// (protected) set from integer value x, -DV <= x < DV
function bnpFromInt(x) {
this.t = 1;
this.s = (x<0)?-1:0;
if(x > 0) this[0] = x;
else if(x < -1) this[0] = x+this.DV;
else this.t = 0;
}
// return bigint initialized to value
function nbv(i) { var r = nbi(); r.fromInt(i); return r; }
// (protected) set from string and radix
function bnpFromString(s,b) {
var k;
if(b == 16) k = 4;
else if(b == 8) k = 3;
else if(b == 256) k = 8; // byte array
else if(b == 2) k = 1;
else if(b == 32) k = 5;
else if(b == 4) k = 2;
else { this.fromRadix(s,b); return; }
this.t = 0;
this.s = 0;
var i = s.length, mi = false, sh = 0;
while(--i >= 0) {
var x = (k==8)?s[i]&0xff:intAt(s,i);
if(x < 0) {
if(s.charAt(i) == "-") mi = true;
continue;
}
mi = false;
if(sh == 0)
this[this.t++] = x;
else if(sh+k > this.DB) {
this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;
this[this.t++] = (x>>(this.DB-sh));
}
else
this[this.t-1] |= x<<sh;
sh += k;
if(sh >= this.DB) sh -= this.DB;
}
if(k == 8 && (s[0]&0x80) != 0) {
this.s = -1;
if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;
}
this.clamp();
if(mi) BigInteger.ZERO.subTo(this,this);
}
// (protected) clamp off excess high words
function bnpClamp() {
var c = this.s&this.DM;
while(this.t > 0 && this[this.t-1] == c) --this.t;
}
// (public) return string representation in given radix
function bnToString(b) {
if(this.s < 0) return "-"+this.negate().toString(b);
var k;
if(b == 16) k = 4;
else if(b == 8) k = 3;
else if(b == 2) k = 1;
else if(b == 32) k = 5;
else if(b == 4) k = 2;
else return this.toRadix(b);
var km = (1<<k)-1, d, m = false, r = "", i = this.t;
var p = this.DB-(i*this.DB)%k;
if(i-- > 0) {
if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }
while(i >= 0) {
if(p < k) {
d = (this[i]&((1<<p)-1))<<(k-p);
d |= this[--i]>>(p+=this.DB-k);
}
else {
d = (this[i]>>(p-=k))&km;
if(p <= 0) { p += this.DB; --i; }
}
if(d > 0) m = true;
if(m) r += int2char(d);
}
}
return m?r:"0";
}
// (public) -this
function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }
// (public) |this|
function bnAbs() { return (this.s<0)?this.negate():this; }
// (public) return + if this > a, - if this < a, 0 if equal
function bnCompareTo(a) {
var r = this.s-a.s;
if(r != 0) return r;
var i = this.t;
r = i-a.t;
if(r != 0) return (this.s<0)?-r:r;
while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;
return 0;
}
// returns bit length of the integer x
function nbits(x) {
var r = 1, t;
if((t=x>>>16) != 0) { x = t; r += 16; }
if((t=x>>8) != 0) { x = t; r += 8; }
if((t=x>>4) != 0) { x = t; r += 4; }
if((t=x>>2) != 0) { x = t; r += 2; }
if((t=x>>1) != 0) { x = t; r += 1; }
return r;
}
// (public) return the number of bits in "this"
function bnBitLength() {
if(this.t <= 0) return 0;
return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));
}
// (protected) r = this << n*DB
function bnpDLShiftTo(n,r) {
var i;
for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];
for(i = n-1; i >= 0; --i) r[i] = 0;
r.t = this.t+n;
r.s = this.s;
}
// (protected) r = this >> n*DB
function bnpDRShiftTo(n,r) {
for(var i = n; i < this.t; ++i) r[i-n] = this[i];
r.t = Math.max(this.t-n,0);
r.s = this.s;
}
// (protected) r = this << n
function bnpLShiftTo(n,r) {
var bs = n%this.DB;
var cbs = this.DB-bs;
var bm = (1<<cbs)-1;
var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;
for(i = this.t-1; i >= 0; --i) {
r[i+ds+1] = (this[i]>>cbs)|c;
c = (this[i]&bm)<<bs;
}
for(i = ds-1; i >= 0; --i) r[i] = 0;
r[ds] = c;
r.t = this.t+ds+1;
r.s = this.s;
r.clamp();
}
// (protected) r = this >> n
function bnpRShiftTo(n,r) {
r.s = this.s;
var ds = Math.floor(n/this.DB);
if(ds >= this.t) { r.t = 0; return; }
var bs = n%this.DB;
var cbs = this.DB-bs;
var bm = (1<<bs)-1;
r[0] = this[ds]>>bs;
for(var i = ds+1; i < this.t; ++i) {
r[i-ds-1] |= (this[i]&bm)<<cbs;
r[i-ds] = this[i]>>bs;
}
if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;
r.t = this.t-ds;
r.clamp();
}
// (protected) r = this - a
function bnpSubTo(a,r) {
var i = 0, c = 0, m = Math.min(a.t,this.t);
while(i < m) {
c += this[i]-a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
if(a.t < this.t) {
c -= a.s;
while(i < this.t) {
c += this[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += this.s;
}
else {
c += this.s;
while(i < a.t) {
c -= a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c -= a.s;
}
r.s = (c<0)?-1:0;
if(c < -1) r[i++] = this.DV+c;
else if(c > 0) r[i++] = c;
r.t = i;
r.clamp();
}
// (protected) r = this * a, r != this,a (HAC 14.12)
// "this" should be the larger one if appropriate.
function bnpMultiplyTo(a,r) {
var x = this.abs(), y = a.abs();
var i = x.t;
r.t = i+y.t;
while(--i >= 0) r[i] = 0;
for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);
r.s = 0;
r.clamp();
if(this.s != a.s) BigInteger.ZERO.subTo(r,r);
}
// (protected) r = this^2, r != this (HAC 14.16)
function bnpSquareTo(r) {
var x = this.abs();
var i = r.t = 2*x.t;
while(--i >= 0) r[i] = 0;
for(i = 0; i < x.t-1; ++i) {
var c = x.am(i,x[i],r,2*i,0,1);
if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {
r[i+x.t] -= x.DV;
r[i+x.t+1] = 1;
}
}
if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);
r.s = 0;
r.clamp();
}
// (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)
// r != q, this != m. q or r may be null.
function bnpDivRemTo(m,q,r) {
var pm = m.abs();
if(pm.t <= 0) return;
var pt = this.abs();
if(pt.t < pm.t) {
if(q != null) q.fromInt(0);
if(r != null) this.copyTo(r);
return;
}
if(r == null) r = nbi();
var y = nbi(), ts = this.s, ms = m.s;
var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus
if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }
else { pm.copyTo(y); pt.copyTo(r); }
var ys = y.t;
var y0 = y[ys-1];
if(y0 == 0) return;
var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);
var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;
var i = r.t, j = i-ys, t = (q==null)?nbi():q;
y.dlShiftTo(j,t);
if(r.compareTo(t) >= 0) {
r[r.t++] = 1;
r.subTo(t,r);
}
BigInteger.ONE.dlShiftTo(ys,t);
t.subTo(y,y); // "negative" y so we can replace sub with am later
while(y.t < ys) y[y.t++] = 0;
while(--j >= 0) {
// Estimate quotient digit
var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);
if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out
y.dlShiftTo(j,t);
r.subTo(t,r);
while(r[i] < --qd) r.subTo(t,r);
}
}
if(q != null) {
r.drShiftTo(ys,q);
if(ts != ms) BigInteger.ZERO.subTo(q,q);
}
r.t = ys;
r.clamp();
if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder
if(ts < 0) BigInteger.ZERO.subTo(r,r);
}
// (public) this mod a
function bnMod(a) {
var r = nbi();
this.abs().divRemTo(a,null,r);
if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);
return r;
}
// Modular reduction using "classic" algorithm
function Classic(m) { this.m = m; }
function cConvert(x) {
if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);
else return x;
}
function cRevert(x) { return x; }
function cReduce(x) { x.divRemTo(this.m,null,x); }
function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
Classic.prototype.convert = cConvert;
Classic.prototype.revert = cRevert;
Classic.prototype.reduce = cReduce;
Classic.prototype.mulTo = cMulTo;
Classic.prototype.sqrTo = cSqrTo;
// (protected) return "-1/this % 2^DB"; useful for Mont. reduction
// justification:
// xy == 1 (mod m)
// xy = 1+km
// xy(2-xy) = (1+km)(1-km)
// x[y(2-xy)] = 1-k^2m^2
// x[y(2-xy)] == 1 (mod m^2)
// if y is 1/x mod m, then y(2-xy) is 1/x mod m^2
// should reduce x and y(2-xy) by m^2 at each step to keep size bounded.
// JS multiply "overflows" differently from C/C++, so care is needed here.
function bnpInvDigit() {
if(this.t < 1) return 0;
var x = this[0];
if((x&1) == 0) return 0;
var y = x&3; // y == 1/x mod 2^2
y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4
y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8
y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16
// last step - calculate inverse mod DV directly;
// assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints
y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits
// we really want the negative inverse, and -DV < y < DV
return (y>0)?this.DV-y:-y;
}
// Montgomery reduction
function Montgomery(m) {
this.m = m;
this.mp = m.invDigit();
this.mpl = this.mp&0x7fff;
this.mph = this.mp>>15;
this.um = (1<<(m.DB-15))-1;
this.mt2 = 2*m.t;
}
// xR mod m
function montConvert(x) {
var r = nbi();
x.abs().dlShiftTo(this.m.t,r);
r.divRemTo(this.m,null,r);
if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);
return r;
}
// x/R mod m
function montRevert(x) {
var r = nbi();
x.copyTo(r);
this.reduce(r);
return r;
}
// x = x/R mod m (HAC 14.32)
function montReduce(x) {
while(x.t <= this.mt2) // pad x so am has enough room later
x[x.t++] = 0;
for(var i = 0; i < this.m.t; ++i) {
// faster way of calculating u0 = x[i]*mp mod DV
var j = x[i]&0x7fff;
var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;
// use am to combine the multiply-shift-add into one call
j = i+this.m.t;
x[j] += this.m.am(0,u0,x,i,0,this.m.t);
// propagate carry
while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }
}
x.clamp();
x.drShiftTo(this.m.t,x);
if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}
// r = "x^2/R mod m"; x != r
function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
// r = "xy/R mod m"; x,y != r
function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
Montgomery.prototype.convert = montConvert;
Montgomery.prototype.revert = montRevert;
Montgomery.prototype.reduce = montReduce;
Montgomery.prototype.mulTo = montMulTo;
Montgomery.prototype.sqrTo = montSqrTo;
// (protected) true iff this is even
function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }
// (protected) this^e, e < 2^32, doing sqr and mul with "r" (HAC 14.79)
function bnpExp(e,z) {
if(e > 0xffffffff || e < 1) return BigInteger.ONE;
var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;
g.copyTo(r);
while(--i >= 0) {
z.sqrTo(r,r2);
if((e&(1<<i)) > 0) z.mulTo(r2,g,r);
else { var t = r; r = r2; r2 = t; }
}
return z.revert(r);
}
// (public) this^e % m, 0 <= e < 2^32
function bnModPowInt(e,m) {
var z;
if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);
return this.exp(e,z);
}
// protected
BigInteger.prototype.copyTo = bnpCopyTo;
BigInteger.prototype.fromInt = bnpFromInt;
BigInteger.prototype.fromString = bnpFromString;
BigInteger.prototype.clamp = bnpClamp;
BigInteger.prototype.dlShiftTo = bnpDLShiftTo;
BigInteger.prototype.drShiftTo = bnpDRShiftTo;
BigInteger.prototype.lShiftTo = bnpLShiftTo;
BigInteger.prototype.rShiftTo = bnpRShiftTo;
BigInteger.prototype.subTo = bnpSubTo;
BigInteger.prototype.multiplyTo = bnpMultiplyTo;
BigInteger.prototype.squareTo = bnpSquareTo;
BigInteger.prototype.divRemTo = bnpDivRemTo;
BigInteger.prototype.invDigit = bnpInvDigit;
BigInteger.prototype.isEven = bnpIsEven;
BigInteger.prototype.exp = bnpExp;
// public
BigInteger.prototype.toString = bnToString;
BigInteger.prototype.negate = bnNegate;
BigInteger.prototype.abs = bnAbs;
BigInteger.prototype.compareTo = bnCompareTo;
BigInteger.prototype.bitLength = bnBitLength;
BigInteger.prototype.mod = bnMod;
BigInteger.prototype.modPowInt = bnModPowInt;
// "constants"
BigInteger.ZERO = nbv(0);
BigInteger.ONE = nbv(1);
// Copyright (c) 2005-2009 Tom Wu
// All Rights Reserved.
// See "LICENSE" for details.
// Extended JavaScript BN functions, required for RSA private ops.
// Version 1.1: new BigInteger("0", 10) returns "proper" zero
// Version 1.2: square() API, isProbablePrime fix
// (public)
function bnClone() { var r = nbi(); this.copyTo(r); return r; }
// (public) return value as integer
function bnIntValue() {
if(this.s < 0) {
if(this.t == 1) return this[0]-this.DV;
else if(this.t == 0) return -1;
}
else if(this.t == 1) return this[0];
else if(this.t == 0) return 0;
// assumes 16 < DB < 32
return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];
}
// (public) return value as byte
function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }
// (public) return value as short (assumes DB>=16)
function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }
// (protected) return x s.t. r^x < DV
function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }
// (public) 0 if this == 0, 1 if this > 0
function bnSigNum() {
if(this.s < 0) return -1;
else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;
else return 1;
}
// (protected) convert to radix string
function bnpToRadix(b) {
if(b == null) b = 10;
if(this.signum() == 0 || b < 2 || b > 36) return "0";
var cs = this.chunkSize(b);
var a = Math.pow(b,cs);
var d = nbv(a), y = nbi(), z = nbi(), r = "";
this.divRemTo(d,y,z);
while(y.signum() > 0) {
r = (a+z.intValue()).toString(b).substr(1) + r;
y.divRemTo(d,y,z);
}
return z.intValue().toString(b) + r;
}
// (protected) convert from radix string
function bnpFromRadix(s,b) {
this.fromInt(0);
if(b == null) b = 10;
var cs = this.chunkSize(b);
var d = Math.pow(b,cs), mi = false, j = 0, w = 0;
for(var i = 0; i < s.length; ++i) {
var x = intAt(s,i);
if(x < 0) {
if(s.charAt(i) == "-" && this.signum() == 0) mi = true;
continue;
}
w = b*w+x;
if(++j >= cs) {
this.dMultiply(d);
this.dAddOffset(w,0);
j = 0;
w = 0;
}
}
if(j > 0) {
this.dMultiply(Math.pow(b,j));
this.dAddOffset(w,0);
}
if(mi) BigInteger.ZERO.subTo(this,this);
}
// (protected) alternate constructor
function bnpFromNumber(a,b,c) {
if("number" == typeof b) {
// new BigInteger(int,int,RNG)
if(a < 2) this.fromInt(1);
else {
this.fromNumber(a,c);
if(!this.testBit(a-1)) // force MSB set
this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);
if(this.isEven()) this.dAddOffset(1,0); // force odd
while(!this.isProbablePrime(b)) {
this.dAddOffset(2,0);
if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);
}
}
}
else {
// new BigInteger(int,RNG)
var x = new Array(), t = a&7;
x.length = (a>>3)+1;
b.nextBytes(x);
if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;
this.fromString(x,256);
}
}
// (public) convert to bigendian byte array
function bnToByteArray() {
var i = this.t, r = new Array();
r[0] = this.s;
var p = this.DB-(i*this.DB)%8, d, k = 0;
if(i-- > 0) {
if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)
r[k++] = d|(this.s<<(this.DB-p));
while(i >= 0) {
if(p < 8) {
d = (this[i]&((1<<p)-1))<<(8-p);
d |= this[--i]>>(p+=this.DB-8);
}
else {
d = (this[i]>>(p-=8))&0xff;
if(p <= 0) { p += this.DB; --i; }
}
if((d&0x80) != 0) d |= -256;
if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;
if(k > 0 || d != this.s) r[k++] = d;
}
}
return r;
}
function bnEquals(a) { return(this.compareTo(a)==0); }
function bnMin(a) { return(this.compareTo(a)<0)?this:a; }
function bnMax(a) { return(this.compareTo(a)>0)?this:a; }
// (protected) r = this op a (bitwise)
function bnpBitwiseTo(a,op,r) {
var i, f, m = Math.min(a.t,this.t);
for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);
if(a.t < this.t) {
f = a.s&this.DM;
for(i = m; i < this.t; ++i) r[i] = op(this[i],f);
r.t = this.t;
}
else {
f = this.s&this.DM;
for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);
r.t = a.t;
}
r.s = op(this.s,a.s);
r.clamp();
}
// (public) this & a
function op_and(x,y) { return x&y; }
function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }
// (public) this | a
function op_or(x,y) { return x|y; }
function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }
// (public) this ^ a
function op_xor(x,y) { return x^y; }
function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }
// (public) this & ~a
function op_andnot(x,y) { return x&~y; }
function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }
// (public) ~this
function bnNot() {
var r = nbi();
for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];
r.t = this.t;
r.s = ~this.s;
return r;
}
// (public) this << n
function bnShiftLeft(n) {
var r = nbi();
if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);
return r;
}
// (public) this >> n
function bnShiftRight(n) {
var r = nbi();
if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);
return r;
}
// return index of lowest 1-bit in x, x < 2^31
function lbit(x) {
if(x == 0) return -1;
var r = 0;
if((x&0xffff) == 0) { x >>= 16; r += 16; }
if((x&0xff) == 0) { x >>= 8; r += 8; }
if((x&0xf) == 0) { x >>= 4; r += 4; }
if((x&3) == 0) { x >>= 2; r += 2; }
if((x&1) == 0) ++r;
return r;
}
// (public) returns index of lowest 1-bit (or -1 if none)
function bnGetLowestSetBit() {
for(var i = 0; i < this.t; ++i)
if(this[i] != 0) return i*this.DB+lbit(this[i]);
if(this.s < 0) return this.t*this.DB;
return -1;
}
// return number of 1 bits in x
function cbit(x) {
var r = 0;
while(x != 0) { x &= x-1; ++r; }
return r;
}
// (public) return number of set bits
function bnBitCount() {
var r = 0, x = this.s&this.DM;
for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);
return r;
}
// (public) true iff nth bit is set
function bnTestBit(n) {
var j = Math.floor(n/this.DB);
if(j >= this.t) return(this.s!=0);
return((this[j]&(1<<(n%this.DB)))!=0);
}
// (protected) this op (1<<n)
function bnpChangeBit(n,op) {
var r = BigInteger.ONE.shiftLeft(n);
this.bitwiseTo(r,op,r);
return r;
}
// (public) this | (1<<n)
function bnSetBit(n) { return this.changeBit(n,op_or); }
// (public) this & ~(1<<n)
function bnClearBit(n) { return this.changeBit(n,op_andnot); }
// (public) this ^ (1<<n)
function bnFlipBit(n) { return this.changeBit(n,op_xor); }
// (protected) r = this + a
function bnpAddTo(a,r) {
var i = 0, c = 0, m = Math.min(a.t,this.t);
while(i < m) {
c += this[i]+a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
if(a.t < this.t) {
c += a.s;
while(i < this.t) {
c += this[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += this.s;
}
else {
c += this.s;
while(i < a.t) {
c += a[i];
r[i++] = c&this.DM;
c >>= this.DB;
}
c += a.s;
}
r.s = (c<0)?-1:0;
if(c > 0) r[i++] = c;
else if(c < -1) r[i++] = this.DV+c;
r.t = i;
r.clamp();
}
// (public) this + a
function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }
// (public) this - a
function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }
// (public) this * a
function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }
// (public) this^2
function bnSquare() { var r = nbi(); this.squareTo(r); return r; }
// (public) this / a
function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }
// (public) this % a
function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }
// (public) [this/a,this%a]
function bnDivideAndRemainder(a) {
var q = nbi(), r = nbi();
this.divRemTo(a,q,r);
return new Array(q,r);
}
// (protected) this *= n, this >= 0, 1 < n < DV
function bnpDMultiply(n) {
this[this.t] = this.am(0,n-1,this,0,0,this.t);
++this.t;
this.clamp();
}
// (protected) this += n << w words, this >= 0
function bnpDAddOffset(n,w) {
if(n == 0) return;
while(this.t <= w) this[this.t++] = 0;
this[w] += n;
while(this[w] >= this.DV) {
this[w] -= this.DV;
if(++w >= this.t) this[this.t++] = 0;
++this[w];
}
}
// A "null" reducer
function NullExp() {}
function nNop(x) { return x; }
function nMulTo(x,y,r) { x.multiplyTo(y,r); }
function nSqrTo(x,r) { x.squareTo(r); }
NullExp.prototype.convert = nNop;
NullExp.prototype.revert = nNop;
NullExp.prototype.mulTo = nMulTo;
NullExp.prototype.sqrTo = nSqrTo;
// (public) this^e
function bnPow(e) { return this.exp(e,new NullExp()); }
// (protected) r = lower n words of "this * a", a.t <= n
// "this" should be the larger one if appropriate.
function bnpMultiplyLowerTo(a,n,r) {
var i = Math.min(this.t+a.t,n);
r.s = 0; // assumes a,this >= 0
r.t = i;
while(i > 0) r[--i] = 0;
var j;
for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);
for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);
r.clamp();
}
// (protected) r = "this * a" without lower n words, n > 0
// "this" should be the larger one if appropriate.
function bnpMultiplyUpperTo(a,n,r) {
--n;
var i = r.t = this.t+a.t-n;
r.s = 0; // assumes a,this >= 0
while(--i >= 0) r[i] = 0;
for(i = Math.max(n-this.t,0); i < a.t; ++i)
r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);
r.clamp();
r.drShiftTo(1,r);
}
// Barrett modular reduction
function Barrett(m) {
// setup Barrett
this.r2 = nbi();
this.q3 = nbi();
BigInteger.ONE.dlShiftTo(2*m.t,this.r2);
this.mu = this.r2.divide(m);
this.m = m;
}
function barrettConvert(x) {
if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);
else if(x.compareTo(this.m) < 0) return x;
else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }
}
function barrettRevert(x) { return x; }
// x = x mod m (HAC 14.42)
function barrettReduce(x) {
x.drShiftTo(this.m.t-1,this.r2);
if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }
this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);
this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);
while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);
x.subTo(this.r2,x);
while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);
}
// r = x^2 mod m; x != r
function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }
// r = x*y mod m; x,y != r
function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }
Barrett.prototype.convert = barrettConvert;
Barrett.prototype.revert = barrettRevert;
Barrett.prototype.reduce = barrettReduce;
Barrett.prototype.mulTo = barrettMulTo;
Barrett.prototype.sqrTo = barrettSqrTo;
// (public) this^e % m (HAC 14.85)
function bnModPow(e,m) {
var i = e.bitLength(), k, r = nbv(1), z;
if(i <= 0) return r;
else if(i < 18) k = 1;
else if(i < 48) k = 3;
else if(i < 144) k = 4;
else if(i < 768) k = 5;
else k = 6;
if(i < 8)
z = new Classic(m);
else if(m.isEven())
z = new Barrett(m);
else
z = new Montgomery(m);
// precomputation
var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;
g[1] = z.convert(this);
if(k > 1) {
var g2 = nbi();
z.sqrTo(g[1],g2);
while(n <= km) {
g[n] = nbi();
z.mulTo(g2,g[n-2],g[n]);
n += 2;
}
}
var j = e.t-1, w, is1 = true, r2 = nbi(), t;
i = nbits(e[j])-1;
while(j >= 0) {
if(i >= k1) w = (e[j]>>(i-k1))&km;
else {
w = (e[j]&((1<<(i+1))-1))<<(k1-i);
if(j > 0) w |= e[j-1]>>(this.DB+i-k1);
}
n = k;
while((w&1) == 0) { w >>= 1; --n; }
if((i -= n) < 0) { i += this.DB; --j; }
if(is1) { // ret == 1, don't bother squaring or multiplying it
g[w].copyTo(r);
is1 = false;
}
else {
while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }
if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }
z.mulTo(r2,g[w],r);
}
while(j >= 0 && (e[j]&(1<<i)) == 0) {
z.sqrTo(r,r2); t = r; r = r2; r2 = t;
if(--i < 0) { i = this.DB-1; --j; }
}
}
return z.revert(r);
}
// (public) gcd(this,a) (HAC 14.54)
function bnGCD(a) {
var x = (this.s<0)?this.negate():this.clone();
var y = (a.s<0)?a.negate():a.clone();
if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }
var i = x.getLowestSetBit(), g = y.getLowestSetBit();
if(g < 0) return x;
if(i < g) g = i;
if(g > 0) {
x.rShiftTo(g,x);
y.rShiftTo(g,y);
}
while(x.signum() > 0) {
if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);
if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);
if(x.compareTo(y) >= 0) {
x.subTo(y,x);
x.rShiftTo(1,x);
}
else {
y.subTo(x,y);
y.rShiftTo(1,y);
}
}
if(g > 0) y.lShiftTo(g,y);
return y;
}
// (protected) this % n, n < 2^26
function bnpModInt(n) {
if(n <= 0) return 0;
var d = this.DV%n, r = (this.s<0)?n-1:0;
if(this.t > 0)
if(d == 0) r = this[0]%n;
else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;
return r;
}
// (public) 1/this % m (HAC 14.61)
function bnModInverse(m) {
var ac = m.isEven();
if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;
var u = m.clone(), v = this.clone();
var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);
while(u.signum() != 0) {
while(u.isEven()) {
u.rShiftTo(1,u);
if(ac) {
if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }
a.rShiftTo(1,a);
}
else if(!b.isEven()) b.subTo(m,b);
b.rShiftTo(1,b);
}
while(v.isEven()) {
v.rShiftTo(1,v);
if(ac) {
if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }
c.rShiftTo(1,c);
}
else if(!d.isEven()) d.subTo(m,d);
d.rShiftTo(1,d);
}
if(u.compareTo(v) >= 0) {
u.subTo(v,u);
if(ac) a.subTo(c,a);
b.subTo(d,b);
}
else {
v.subTo(u,v);
if(ac) c.subTo(a,c);
d.subTo(b,d);
}
}
if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;
if(d.compareTo(m) >= 0) return d.subtract(m);
if(d.signum() < 0) d.addTo(m,d); else return d;
if(d.signum() < 0) return d.add(m); else return d;
}
var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];
var lplim = (1<<26)/lowprimes[lowprimes.length-1];
// (public) test primality with certainty >= 1-.5^t
function bnIsProbablePrime(t) {
var i, x = this.abs();
if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {
for(i = 0; i < lowprimes.length; ++i)
if(x[0] == lowprimes[i]) return true;
return false;
}
if(x.isEven()) return false;
i = 1;
while(i < lowprimes.length) {
var m = lowprimes[i], j = i+1;
while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];
m = x.modInt(m);
while(i < j) if(m%lowprimes[i++] == 0) return false;
}
return x.millerRabin(t);
}
// (protected) true if probably prime (HAC 4.24, Miller-Rabin)
function bnpMillerRabin(t) {
var n1 = this.subtract(BigInteger.ONE);
var k = n1.getLowestSetBit();
if(k <= 0) return false;
var r = n1.shiftRight(k);
t = (t+1)>>1;
if(t > lowprimes.length) t = lowprimes.length;
var a = nbi();
for(var i = 0; i < t; ++i) {
//Pick bases at random, instead of starting at 2
a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);
var y = a.modPow(r,this);
if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {
var j = 1;
while(j++ < k && y.compareTo(n1) != 0) {
y = y.modPowInt(2,this);
if(y.compareTo(BigInteger.ONE) == 0) return false;
}
if(y.compareTo(n1) != 0) return false;
}
}
return true;
}
// protected
BigInteger.prototype.chunkSize = bnpChunkSize;
BigInteger.prototype.toRadix = bnpToRadix;
BigInteger.prototype.fromRadix = bnpFromRadix;
BigInteger.prototype.fromNumber = bnpFromNumber;
BigInteger.prototype.bitwiseTo = bnpBitwiseTo;
BigInteger.prototype.changeBit = bnpChangeBit;
BigInteger.prototype.addTo = bnpAddTo;
BigInteger.prototype.dMultiply = bnpDMultiply;
BigInteger.prototype.dAddOffset = bnpDAddOffset;
BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;
BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;
BigInteger.prototype.modInt = bnpModInt;
BigInteger.prototype.millerRabin = bnpMillerRabin;
// public
BigInteger.prototype.clone = bnClone;
BigInteger.prototype.intValue = bnIntValue;
BigInteger.prototype.byteValue = bnByteValue;
BigInteger.prototype.shortValue = bnShortValue;
BigInteger.prototype.signum = bnSigNum;
BigInteger.prototype.toByteArray = bnToByteArray;
BigInteger.prototype.equals = bnEquals;
BigInteger.prototype.min = bnMin;
BigInteger.prototype.max = bnMax;
BigInteger.prototype.and = bnAnd;
BigInteger.prototype.or = bnOr;
BigInteger.prototype.xor = bnXor;
BigInteger.prototype.andNot = bnAndNot;
BigInteger.prototype.not = bnNot;
BigInteger.prototype.shiftLeft = bnShiftLeft;
BigInteger.prototype.shiftRight = bnShiftRight;
BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;
BigInteger.prototype.bitCount = bnBitCount;
BigInteger.prototype.testBit = bnTestBit;
BigInteger.prototype.setBit = bnSetBit;
BigInteger.prototype.clearBit = bnClearBit;
BigInteger.prototype.flipBit = bnFlipBit;
BigInteger.prototype.add = bnAdd;
BigInteger.prototype.subtract = bnSubtract;
BigInteger.prototype.multiply = bnMultiply;
BigInteger.prototype.divide = bnDivide;
BigInteger.prototype.remainder = bnRemainder;
BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;
BigInteger.prototype.modPow = bnModPow;
BigInteger.prototype.modInverse = bnModInverse;
BigInteger.prototype.pow = bnPow;
BigInteger.prototype.gcd = bnGCD;
BigInteger.prototype.isProbablePrime = bnIsProbablePrime;
// JSBN-specific extension
BigInteger.prototype.square = bnSquare;
// Expose the Barrett function
BigInteger.prototype.Barrett = Barrett
// BigInteger interfaces not implemented in jsbn:
// BigInteger(int signum, byte[] magnitude)
// double doubleValue()
// float floatValue()
// int hashCode()
// long longValue()
// static BigInteger valueOf(long val)
// Random number generator - requires a PRNG backend, e.g. prng4.js
// For best results, put code like
// <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>
// in your main HTML document.
var rng_state;
var rng_pool;
var rng_pptr;
// Mix in a 32-bit integer into the pool
function rng_seed_int(x) {
rng_pool[rng_pptr++] ^= x & 255;
rng_pool[rng_pptr++] ^= (x >> 8) & 255;
rng_pool[rng_pptr++] ^= (x >> 16) & 255;
rng_pool[rng_pptr++] ^= (x >> 24) & 255;
if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;
}
// Mix in the current time (w/milliseconds) into the pool
function rng_seed_time() {
rng_seed_int(new Date().getTime());
}
// Initialize the pool with junk if needed.
if(rng_pool == null) {
rng_pool = new Array();
rng_pptr = 0;
var t;
if(typeof window !== "undefined" && window.crypto) {
if (window.crypto.getRandomValues) {
// Use webcrypto if available
var ua = new Uint8Array(32);
window.crypto.getRandomValues(ua);
for(t = 0; t < 32; ++t)
rng_pool[rng_pptr++] = ua[t];
}
else if(navigator.appName == "Netscape" && navigator.appVersion < "5") {
// Extract entropy (256 bits) from NS4 RNG if available
var z = window.crypto.random(32);
for(t = 0; t < z.length; ++t)
rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;
}
}
while(rng_pptr < rng_psize) { // extract some randomness from Math.random()
t = Math.floor(65536 * Math.random());
rng_pool[rng_pptr++] = t >>> 8;
rng_pool[rng_pptr++] = t & 255;
}
rng_pptr = 0;
rng_seed_time();
//rng_seed_int(window.screenX);
//rng_seed_int(window.screenY);
}
function rng_get_byte() {
if(rng_state == null) {
rng_seed_time();
rng_state = prng_newstate();
rng_state.init(rng_pool);
for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)
rng_pool[rng_pptr] = 0;
rng_pptr = 0;
//rng_pool = null;
}
// TODO: allow reseeding after first request
return rng_state.next();
}
function rng_get_bytes(ba) {
var i;
for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();
}
function SecureRandom() {}
SecureRandom.prototype.nextBytes = rng_get_bytes;
// prng4.js - uses Arcfour as a PRNG
function Arcfour() {
this.i = 0;
this.j = 0;
this.S = new Array();
}
// Initialize arcfour context from key, an array of ints, each from [0..255]
function ARC4init(key) {
var i, j, t;
for(i = 0; i < 256; ++i)
this.S[i] = i;
j = 0;
for(i = 0; i < 256; ++i) {
j = (j + this.S[i] + key[i % key.length]) & 255;
t = this.S[i];
this.S[i] = this.S[j];
this.S[j] = t;
}
this.i = 0;
this.j = 0;
}
function ARC4next() {
var t;
this.i = (this.i + 1) & 255;
this.j = (this.j + this.S[this.i]) & 255;
t = this.S[this.i];
this.S[this.i] = this.S[this.j];
this.S[this.j] = t;
return this.S[(t + this.S[this.i]) & 255];
}
Arcfour.prototype.init = ARC4init;
Arcfour.prototype.next = ARC4next;
// Plug in your RNG constructor here
function prng_newstate() {
return new Arcfour();
}
// Pool size must be a multiple of 4 and greater than 32.
// An array of bytes the size of the pool will be passed to init()
var rng_psize = 256;
if (typeof exports !== 'undefined') {
exports = module.exports = {
default: BigInteger,
BigInteger: BigInteger,
SecureRandom: SecureRandom,
};
} else {
this.jsbn = {
BigInteger: BigInteger,
SecureRandom: SecureRandom
};
}
}).call(this);
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921835);
})()
//miniprogram-npm-outsideDeps=[]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["index.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["(function(){\n\n // Copyright (c) 2005 Tom Wu\n // All Rights Reserved.\n // See \"LICENSE\" for details.\n\n // Basic JavaScript BN library - subset useful for RSA encryption.\n\n // Bits per digit\n var dbits;\n\n // JavaScript engine analysis\n var canary = 0xdeadbeefcafe;\n var j_lm = ((canary&0xffffff)==0xefcafe);\n\n // (public) Constructor\n function BigInteger(a,b,c) {\n if(a != null)\n if(\"number\" == typeof a) this.fromNumber(a,b,c);\n else if(b == null && \"string\" != typeof a) this.fromString(a,256);\n else this.fromString(a,b);\n }\n\n // return new, unset BigInteger\n function nbi() { return new BigInteger(null); }\n\n // am: Compute w_j += (x*this_i), propagate carries,\n // c is initial carry, returns final carry.\n // c < 3*dvalue, x < 2*dvalue, this_i < dvalue\n // We need to select the fastest one that works in this environment.\n\n // am1: use a single mult and divide to get the high bits,\n // max digit bits should be 26 because\n // max internal value = 2*dvalue^2-2*dvalue (< 2^53)\n function am1(i,x,w,j,c,n) {\n while(--n >= 0) {\n var v = x*this[i++]+w[j]+c;\n c = Math.floor(v/0x4000000);\n w[j++] = v&0x3ffffff;\n }\n return c;\n }\n // am2 avoids a big mult-and-extract completely.\n // Max digit bits should be <= 30 because we do bitwise ops\n // on values up to 2*hdvalue^2-hdvalue-1 (< 2^31)\n function am2(i,x,w,j,c,n) {\n var xl = x&0x7fff, xh = x>>15;\n while(--n >= 0) {\n var l = this[i]&0x7fff;\n var h = this[i++]>>15;\n var m = xh*l+h*xl;\n l = xl*l+((m&0x7fff)<<15)+w[j]+(c&0x3fffffff);\n c = (l>>>30)+(m>>>15)+xh*h+(c>>>30);\n w[j++] = l&0x3fffffff;\n }\n return c;\n }\n // Alternately, set max digit bits to 28 since some\n // browsers slow down when dealing with 32-bit numbers.\n function am3(i,x,w,j,c,n) {\n var xl = x&0x3fff, xh = x>>14;\n while(--n >= 0) {\n var l = this[i]&0x3fff;\n var h = this[i++]>>14;\n var m = xh*l+h*xl;\n l = xl*l+((m&0x3fff)<<14)+w[j]+c;\n c = (l>>28)+(m>>14)+xh*h;\n w[j++] = l&0xfffffff;\n }\n return c;\n }\n var inBrowser = typeof navigator !== \"undefined\";\n if(inBrowser && j_lm && (navigator.appName == \"Microsoft Internet Explorer\")) {\n BigInteger.prototype.am = am2;\n dbits = 30;\n }\n else if(inBrowser && j_lm && (navigator.appName != \"Netscape\")) {\n BigInteger.prototype.am = am1;\n dbits = 26;\n }\n else { // Mozilla/Netscape seems to prefer am3\n BigInteger.prototype.am = am3;\n dbits = 28;\n }\n\n BigInteger.prototype.DB = dbits;\n BigInteger.prototype.DM = ((1<<dbits)-1);\n BigInteger.prototype.DV = (1<<dbits);\n\n var BI_FP = 52;\n BigInteger.prototype.FV = Math.pow(2,BI_FP);\n BigInteger.prototype.F1 = BI_FP-dbits;\n BigInteger.prototype.F2 = 2*dbits-BI_FP;\n\n // Digit conversions\n var BI_RM = \"0123456789abcdefghijklmnopqrstuvwxyz\";\n var BI_RC = new Array();\n var rr,vv;\n rr = \"0\".charCodeAt(0);\n for(vv = 0; vv <= 9; ++vv) BI_RC[rr++] = vv;\n rr = \"a\".charCodeAt(0);\n for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;\n rr = \"A\".charCodeAt(0);\n for(vv = 10; vv < 36; ++vv) BI_RC[rr++] = vv;\n\n function int2char(n) { return BI_RM.charAt(n); }\n function intAt(s,i) {\n var c = BI_RC[s.charCodeAt(i)];\n return (c==null)?-1:c;\n }\n\n // (protected) copy this to r\n function bnpCopyTo(r) {\n for(var i = this.t-1; i >= 0; --i) r[i] = this[i];\n r.t = this.t;\n r.s = this.s;\n }\n\n // (protected) set from integer value x, -DV <= x < DV\n function bnpFromInt(x) {\n this.t = 1;\n this.s = (x<0)?-1:0;\n if(x > 0) this[0] = x;\n else if(x < -1) this[0] = x+this.DV;\n else this.t = 0;\n }\n\n // return bigint initialized to value\n function nbv(i) { var r = nbi(); r.fromInt(i); return r; }\n\n // (protected) set from string and radix\n function bnpFromString(s,b) {\n var k;\n if(b == 16) k = 4;\n else if(b == 8) k = 3;\n else if(b == 256) k = 8; // byte array\n else if(b == 2) k = 1;\n else if(b == 32) k = 5;\n else if(b == 4) k = 2;\n else { this.fromRadix(s,b); return; }\n this.t = 0;\n this.s = 0;\n var i = s.length, mi = false, sh = 0;\n while(--i >= 0) {\n var x = (k==8)?s[i]&0xff:intAt(s,i);\n if(x < 0) {\n if(s.charAt(i) == \"-\") mi = true;\n continue;\n }\n mi = false;\n if(sh == 0)\n this[this.t++] = x;\n else if(sh+k > this.DB) {\n this[this.t-1] |= (x&((1<<(this.DB-sh))-1))<<sh;\n this[this.t++] = (x>>(this.DB-sh));\n }\n else\n this[this.t-1] |= x<<sh;\n sh += k;\n if(sh >= this.DB) sh -= this.DB;\n }\n if(k == 8 && (s[0]&0x80) != 0) {\n this.s = -1;\n if(sh > 0) this[this.t-1] |= ((1<<(this.DB-sh))-1)<<sh;\n }\n this.clamp();\n if(mi) BigInteger.ZERO.subTo(this,this);\n }\n\n // (protected) clamp off excess high words\n function bnpClamp() {\n var c = this.s&this.DM;\n while(this.t > 0 && this[this.t-1] == c) --this.t;\n }\n\n // (public) return string representation in given radix\n function bnToString(b) {\n if(this.s < 0) return \"-\"+this.negate().toString(b);\n var k;\n if(b == 16) k = 4;\n else if(b == 8) k = 3;\n else if(b == 2) k = 1;\n else if(b == 32) k = 5;\n else if(b == 4) k = 2;\n else return this.toRadix(b);\n var km = (1<<k)-1, d, m = false, r = \"\", i = this.t;\n var p = this.DB-(i*this.DB)%k;\n if(i-- > 0) {\n if(p < this.DB && (d = this[i]>>p) > 0) { m = true; r = int2char(d); }\n while(i >= 0) {\n if(p < k) {\n d = (this[i]&((1<<p)-1))<<(k-p);\n d |= this[--i]>>(p+=this.DB-k);\n }\n else {\n d = (this[i]>>(p-=k))&km;\n if(p <= 0) { p += this.DB; --i; }\n }\n if(d > 0) m = true;\n if(m) r += int2char(d);\n }\n }\n return m?r:\"0\";\n }\n\n // (public) -this\n function bnNegate() { var r = nbi(); BigInteger.ZERO.subTo(this,r); return r; }\n\n // (public) |this|\n function bnAbs() { return (this.s<0)?this.negate():this; }\n\n // (public) return + if this > a, - if this < a, 0 if equal\n function bnCompareTo(a) {\n var r = this.s-a.s;\n if(r != 0) return r;\n var i = this.t;\n r = i-a.t;\n if(r != 0) return (this.s<0)?-r:r;\n while(--i >= 0) if((r=this[i]-a[i]) != 0) return r;\n return 0;\n }\n\n // returns bit length of the integer x\n function nbits(x) {\n var r = 1, t;\n if((t=x>>>16) != 0) { x = t; r += 16; }\n if((t=x>>8) != 0) { x = t; r += 8; }\n if((t=x>>4) != 0) { x = t; r += 4; }\n if((t=x>>2) != 0) { x = t; r += 2; }\n if((t=x>>1) != 0) { x = t; r += 1; }\n return r;\n }\n\n // (public) return the number of bits in \"this\"\n function bnBitLength() {\n if(this.t <= 0) return 0;\n return this.DB*(this.t-1)+nbits(this[this.t-1]^(this.s&this.DM));\n }\n\n // (protected) r = this << n*DB\n function bnpDLShiftTo(n,r) {\n var i;\n for(i = this.t-1; i >= 0; --i) r[i+n] = this[i];\n for(i = n-1; i >= 0; --i) r[i] = 0;\n r.t = this.t+n;\n r.s = this.s;\n }\n\n // (protected) r = this >> n*DB\n function bnpDRShiftTo(n,r) {\n for(var i = n; i < this.t; ++i) r[i-n] = this[i];\n r.t = Math.max(this.t-n,0);\n r.s = this.s;\n }\n\n // (protected) r = this << n\n function bnpLShiftTo(n,r) {\n var bs = n%this.DB;\n var cbs = this.DB-bs;\n var bm = (1<<cbs)-1;\n var ds = Math.floor(n/this.DB), c = (this.s<<bs)&this.DM, i;\n for(i = this.t-1; i >= 0; --i) {\n r[i+ds+1] = (this[i]>>cbs)|c;\n c = (this[i]&bm)<<bs;\n }\n for(i = ds-1; i >= 0; --i) r[i] = 0;\n r[ds] = c;\n r.t = this.t+ds+1;\n r.s = this.s;\n r.clamp();\n }\n\n // (protected) r = this >> n\n function bnpRShiftTo(n,r) {\n r.s = this.s;\n var ds = Math.floor(n/this.DB);\n if(ds >= this.t) { r.t = 0; return; }\n var bs = n%this.DB;\n var cbs = this.DB-bs;\n var bm = (1<<bs)-1;\n r[0] = this[ds]>>bs;\n for(var i = ds+1; i < this.t; ++i) {\n r[i-ds-1] |= (this[i]&bm)<<cbs;\n r[i-ds] = this[i]>>bs;\n }\n if(bs > 0) r[this.t-ds-1] |= (this.s&bm)<<cbs;\n r.t = this.t-ds;\n r.clamp();\n }\n\n // (protected) r = this - a\n function bnpSubTo(a,r) {\n var i = 0, c = 0, m = Math.min(a.t,this.t);\n while(i < m) {\n c += this[i]-a[i];\n r[i++] = c&this.DM;\n c >>= this.DB;\n }\n if(a.t < this.t) {\n c -= a.s;\n while(i < this.t) {\n c += this[i];\n r[i++] = c&this.DM;\n c >>= this.DB;\n }\n c += this.s;\n }\n else {\n c += this.s;\n while(i < a.t) {\n c -= a[i];\n r[i++] = c&this.DM;\n c >>= this.DB;\n }\n c -= a.s;\n }\n r.s = (c<0)?-1:0;\n if(c < -1) r[i++] = this.DV+c;\n else if(c > 0) r[i++] = c;\n r.t = i;\n r.clamp();\n }\n\n // (protected) r = this * a, r != this,a (HAC 14.12)\n // \"this\" should be the larger one if appropriate.\n function bnpMultiplyTo(a,r) {\n var x = this.abs(), y = a.abs();\n var i = x.t;\n r.t = i+y.t;\n while(--i >= 0) r[i] = 0;\n for(i = 0; i < y.t; ++i) r[i+x.t] = x.am(0,y[i],r,i,0,x.t);\n r.s = 0;\n r.clamp();\n if(this.s != a.s) BigInteger.ZERO.subTo(r,r);\n }\n\n // (protected) r = this^2, r != this (HAC 14.16)\n function bnpSquareTo(r) {\n var x = this.abs();\n var i = r.t = 2*x.t;\n while(--i >= 0) r[i] = 0;\n for(i = 0; i < x.t-1; ++i) {\n var c = x.am(i,x[i],r,2*i,0,1);\n if((r[i+x.t]+=x.am(i+1,2*x[i],r,2*i+1,c,x.t-i-1)) >= x.DV) {\n r[i+x.t] -= x.DV;\n r[i+x.t+1] = 1;\n }\n }\n if(r.t > 0) r[r.t-1] += x.am(i,x[i],r,2*i,0,1);\n r.s = 0;\n r.clamp();\n }\n\n // (protected) divide this by m, quotient and remainder to q, r (HAC 14.20)\n // r != q, this != m. q or r may be null.\n function bnpDivRemTo(m,q,r) {\n var pm = m.abs();\n if(pm.t <= 0) return;\n var pt = this.abs();\n if(pt.t < pm.t) {\n if(q != null) q.fromInt(0);\n if(r != null) this.copyTo(r);\n return;\n }\n if(r == null) r = nbi();\n var y = nbi(), ts = this.s, ms = m.s;\n var nsh = this.DB-nbits(pm[pm.t-1]); // normalize modulus\n if(nsh > 0) { pm.lShiftTo(nsh,y); pt.lShiftTo(nsh,r); }\n else { pm.copyTo(y); pt.copyTo(r); }\n var ys = y.t;\n var y0 = y[ys-1];\n if(y0 == 0) return;\n var yt = y0*(1<<this.F1)+((ys>1)?y[ys-2]>>this.F2:0);\n var d1 = this.FV/yt, d2 = (1<<this.F1)/yt, e = 1<<this.F2;\n var i = r.t, j = i-ys, t = (q==null)?nbi():q;\n y.dlShiftTo(j,t);\n if(r.compareTo(t) >= 0) {\n r[r.t++] = 1;\n r.subTo(t,r);\n }\n BigInteger.ONE.dlShiftTo(ys,t);\n t.subTo(y,y); // \"negative\" y so we can replace sub with am later\n while(y.t < ys) y[y.t++] = 0;\n while(--j >= 0) {\n // Estimate quotient digit\n var qd = (r[--i]==y0)?this.DM:Math.floor(r[i]*d1+(r[i-1]+e)*d2);\n if((r[i]+=y.am(0,qd,r,j,0,ys)) < qd) { // Try it out\n y.dlShiftTo(j,t);\n r.subTo(t,r);\n while(r[i] < --qd) r.subTo(t,r);\n }\n }\n if(q != null) {\n r.drShiftTo(ys,q);\n if(ts != ms) BigInteger.ZERO.subTo(q,q);\n }\n r.t = ys;\n r.clamp();\n if(nsh > 0) r.rShiftTo(nsh,r); // Denormalize remainder\n if(ts < 0) BigInteger.ZERO.subTo(r,r);\n }\n\n // (public) this mod a\n function bnMod(a) {\n var r = nbi();\n this.abs().divRemTo(a,null,r);\n if(this.s < 0 && r.compareTo(BigInteger.ZERO) > 0) a.subTo(r,r);\n return r;\n }\n\n // Modular reduction using \"classic\" algorithm\n function Classic(m) { this.m = m; }\n function cConvert(x) {\n if(x.s < 0 || x.compareTo(this.m) >= 0) return x.mod(this.m);\n else return x;\n }\n function cRevert(x) { return x; }\n function cReduce(x) { x.divRemTo(this.m,null,x); }\n function cMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\n function cSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\n Classic.prototype.convert = cConvert;\n Classic.prototype.revert = cRevert;\n Classic.prototype.reduce = cReduce;\n Classic.prototype.mulTo = cMulTo;\n Classic.prototype.sqrTo = cSqrTo;\n\n // (protected) return \"-1/this % 2^DB\"; useful for Mont. reduction\n // justification:\n // xy == 1 (mod m)\n // xy = 1+km\n // xy(2-xy) = (1+km)(1-km)\n // x[y(2-xy)] = 1-k^2m^2\n // x[y(2-xy)] == 1 (mod m^2)\n // if y is 1/x mod m, then y(2-xy) is 1/x mod m^2\n // should reduce x and y(2-xy) by m^2 at each step to keep size bounded.\n // JS multiply \"overflows\" differently from C/C++, so care is needed here.\n function bnpInvDigit() {\n if(this.t < 1) return 0;\n var x = this[0];\n if((x&1) == 0) return 0;\n var y = x&3; // y == 1/x mod 2^2\n y = (y*(2-(x&0xf)*y))&0xf; // y == 1/x mod 2^4\n y = (y*(2-(x&0xff)*y))&0xff; // y == 1/x mod 2^8\n y = (y*(2-(((x&0xffff)*y)&0xffff)))&0xffff; // y == 1/x mod 2^16\n // last step - calculate inverse mod DV directly;\n // assumes 16 < DB <= 32 and assumes ability to handle 48-bit ints\n y = (y*(2-x*y%this.DV))%this.DV; // y == 1/x mod 2^dbits\n // we really want the negative inverse, and -DV < y < DV\n return (y>0)?this.DV-y:-y;\n }\n\n // Montgomery reduction\n function Montgomery(m) {\n this.m = m;\n this.mp = m.invDigit();\n this.mpl = this.mp&0x7fff;\n this.mph = this.mp>>15;\n this.um = (1<<(m.DB-15))-1;\n this.mt2 = 2*m.t;\n }\n\n // xR mod m\n function montConvert(x) {\n var r = nbi();\n x.abs().dlShiftTo(this.m.t,r);\n r.divRemTo(this.m,null,r);\n if(x.s < 0 && r.compareTo(BigInteger.ZERO) > 0) this.m.subTo(r,r);\n return r;\n }\n\n // x/R mod m\n function montRevert(x) {\n var r = nbi();\n x.copyTo(r);\n this.reduce(r);\n return r;\n }\n\n // x = x/R mod m (HAC 14.32)\n function montReduce(x) {\n while(x.t <= this.mt2) // pad x so am has enough room later\n x[x.t++] = 0;\n for(var i = 0; i < this.m.t; ++i) {\n // faster way of calculating u0 = x[i]*mp mod DV\n var j = x[i]&0x7fff;\n var u0 = (j*this.mpl+(((j*this.mph+(x[i]>>15)*this.mpl)&this.um)<<15))&x.DM;\n // use am to combine the multiply-shift-add into one call\n j = i+this.m.t;\n x[j] += this.m.am(0,u0,x,i,0,this.m.t);\n // propagate carry\n while(x[j] >= x.DV) { x[j] -= x.DV; x[++j]++; }\n }\n x.clamp();\n x.drShiftTo(this.m.t,x);\n if(x.compareTo(this.m) >= 0) x.subTo(this.m,x);\n }\n\n // r = \"x^2/R mod m\"; x != r\n function montSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\n // r = \"xy/R mod m\"; x,y != r\n function montMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\n\n Montgomery.prototype.convert = montConvert;\n Montgomery.prototype.revert = montRevert;\n Montgomery.prototype.reduce = montReduce;\n Montgomery.prototype.mulTo = montMulTo;\n Montgomery.prototype.sqrTo = montSqrTo;\n\n // (protected) true iff this is even\n function bnpIsEven() { return ((this.t>0)?(this[0]&1):this.s) == 0; }\n\n // (protected) this^e, e < 2^32, doing sqr and mul with \"r\" (HAC 14.79)\n function bnpExp(e,z) {\n if(e > 0xffffffff || e < 1) return BigInteger.ONE;\n var r = nbi(), r2 = nbi(), g = z.convert(this), i = nbits(e)-1;\n g.copyTo(r);\n while(--i >= 0) {\n z.sqrTo(r,r2);\n if((e&(1<<i)) > 0) z.mulTo(r2,g,r);\n else { var t = r; r = r2; r2 = t; }\n }\n return z.revert(r);\n }\n\n // (public) this^e % m, 0 <= e < 2^32\n function bnModPowInt(e,m) {\n var z;\n if(e < 256 || m.isEven()) z = new Classic(m); else z = new Montgomery(m);\n return this.exp(e,z);\n }\n\n // protected\n BigInteger.prototype.copyTo = bnpCopyTo;\n BigInteger.prototype.fromInt = bnpFromInt;\n BigInteger.prototype.fromString = bnpFromString;\n BigInteger.prototype.clamp = bnpClamp;\n BigInteger.prototype.dlShiftTo = bnpDLShiftTo;\n BigInteger.prototype.drShiftTo = bnpDRShiftTo;\n BigInteger.prototype.lShiftTo = bnpLShiftTo;\n BigInteger.prototype.rShiftTo = bnpRShiftTo;\n BigInteger.prototype.subTo = bnpSubTo;\n BigInteger.prototype.multiplyTo = bnpMultiplyTo;\n BigInteger.prototype.squareTo = bnpSquareTo;\n BigInteger.prototype.divRemTo = bnpDivRemTo;\n BigInteger.prototype.invDigit = bnpInvDigit;\n BigInteger.prototype.isEven = bnpIsEven;\n BigInteger.prototype.exp = bnpExp;\n\n // public\n BigInteger.prototype.toString = bnToString;\n BigInteger.prototype.negate = bnNegate;\n BigInteger.prototype.abs = bnAbs;\n BigInteger.prototype.compareTo = bnCompareTo;\n BigInteger.prototype.bitLength = bnBitLength;\n BigInteger.prototype.mod = bnMod;\n BigInteger.prototype.modPowInt = bnModPowInt;\n\n // \"constants\"\n BigInteger.ZERO = nbv(0);\n BigInteger.ONE = nbv(1);\n\n // Copyright (c) 2005-2009 Tom Wu\n // All Rights Reserved.\n // See \"LICENSE\" for details.\n\n // Extended JavaScript BN functions, required for RSA private ops.\n\n // Version 1.1: new BigInteger(\"0\", 10) returns \"proper\" zero\n // Version 1.2: square() API, isProbablePrime fix\n\n // (public)\n function bnClone() { var r = nbi(); this.copyTo(r); return r; }\n\n // (public) return value as integer\n function bnIntValue() {\n if(this.s < 0) {\n if(this.t == 1) return this[0]-this.DV;\n else if(this.t == 0) return -1;\n }\n else if(this.t == 1) return this[0];\n else if(this.t == 0) return 0;\n // assumes 16 < DB < 32\n return ((this[1]&((1<<(32-this.DB))-1))<<this.DB)|this[0];\n }\n\n // (public) return value as byte\n function bnByteValue() { return (this.t==0)?this.s:(this[0]<<24)>>24; }\n\n // (public) return value as short (assumes DB>=16)\n function bnShortValue() { return (this.t==0)?this.s:(this[0]<<16)>>16; }\n\n // (protected) return x s.t. r^x < DV\n function bnpChunkSize(r) { return Math.floor(Math.LN2*this.DB/Math.log(r)); }\n\n // (public) 0 if this == 0, 1 if this > 0\n function bnSigNum() {\n if(this.s < 0) return -1;\n else if(this.t <= 0 || (this.t == 1 && this[0] <= 0)) return 0;\n else return 1;\n }\n\n // (protected) convert to radix string\n function bnpToRadix(b) {\n if(b == null) b = 10;\n if(this.signum() == 0 || b < 2 || b > 36) return \"0\";\n var cs = this.chunkSize(b);\n var a = Math.pow(b,cs);\n var d = nbv(a), y = nbi(), z = nbi(), r = \"\";\n this.divRemTo(d,y,z);\n while(y.signum() > 0) {\n r = (a+z.intValue()).toString(b).substr(1) + r;\n y.divRemTo(d,y,z);\n }\n return z.intValue().toString(b) + r;\n }\n\n // (protected) convert from radix string\n function bnpFromRadix(s,b) {\n this.fromInt(0);\n if(b == null) b = 10;\n var cs = this.chunkSize(b);\n var d = Math.pow(b,cs), mi = false, j = 0, w = 0;\n for(var i = 0; i < s.length; ++i) {\n var x = intAt(s,i);\n if(x < 0) {\n if(s.charAt(i) == \"-\" && this.signum() == 0) mi = true;\n continue;\n }\n w = b*w+x;\n if(++j >= cs) {\n this.dMultiply(d);\n this.dAddOffset(w,0);\n j = 0;\n w = 0;\n }\n }\n if(j > 0) {\n this.dMultiply(Math.pow(b,j));\n this.dAddOffset(w,0);\n }\n if(mi) BigInteger.ZERO.subTo(this,this);\n }\n\n // (protected) alternate constructor\n function bnpFromNumber(a,b,c) {\n if(\"number\" == typeof b) {\n // new BigInteger(int,int,RNG)\n if(a < 2) this.fromInt(1);\n else {\n this.fromNumber(a,c);\n if(!this.testBit(a-1)) // force MSB set\n this.bitwiseTo(BigInteger.ONE.shiftLeft(a-1),op_or,this);\n if(this.isEven()) this.dAddOffset(1,0); // force odd\n while(!this.isProbablePrime(b)) {\n this.dAddOffset(2,0);\n if(this.bitLength() > a) this.subTo(BigInteger.ONE.shiftLeft(a-1),this);\n }\n }\n }\n else {\n // new BigInteger(int,RNG)\n var x = new Array(), t = a&7;\n x.length = (a>>3)+1;\n b.nextBytes(x);\n if(t > 0) x[0] &= ((1<<t)-1); else x[0] = 0;\n this.fromString(x,256);\n }\n }\n\n // (public) convert to bigendian byte array\n function bnToByteArray() {\n var i = this.t, r = new Array();\n r[0] = this.s;\n var p = this.DB-(i*this.DB)%8, d, k = 0;\n if(i-- > 0) {\n if(p < this.DB && (d = this[i]>>p) != (this.s&this.DM)>>p)\n r[k++] = d|(this.s<<(this.DB-p));\n while(i >= 0) {\n if(p < 8) {\n d = (this[i]&((1<<p)-1))<<(8-p);\n d |= this[--i]>>(p+=this.DB-8);\n }\n else {\n d = (this[i]>>(p-=8))&0xff;\n if(p <= 0) { p += this.DB; --i; }\n }\n if((d&0x80) != 0) d |= -256;\n if(k == 0 && (this.s&0x80) != (d&0x80)) ++k;\n if(k > 0 || d != this.s) r[k++] = d;\n }\n }\n return r;\n }\n\n function bnEquals(a) { return(this.compareTo(a)==0); }\n function bnMin(a) { return(this.compareTo(a)<0)?this:a; }\n function bnMax(a) { return(this.compareTo(a)>0)?this:a; }\n\n // (protected) r = this op a (bitwise)\n function bnpBitwiseTo(a,op,r) {\n var i, f, m = Math.min(a.t,this.t);\n for(i = 0; i < m; ++i) r[i] = op(this[i],a[i]);\n if(a.t < this.t) {\n f = a.s&this.DM;\n for(i = m; i < this.t; ++i) r[i] = op(this[i],f);\n r.t = this.t;\n }\n else {\n f = this.s&this.DM;\n for(i = m; i < a.t; ++i) r[i] = op(f,a[i]);\n r.t = a.t;\n }\n r.s = op(this.s,a.s);\n r.clamp();\n }\n\n // (public) this & a\n function op_and(x,y) { return x&y; }\n function bnAnd(a) { var r = nbi(); this.bitwiseTo(a,op_and,r); return r; }\n\n // (public) this | a\n function op_or(x,y) { return x|y; }\n function bnOr(a) { var r = nbi(); this.bitwiseTo(a,op_or,r); return r; }\n\n // (public) this ^ a\n function op_xor(x,y) { return x^y; }\n function bnXor(a) { var r = nbi(); this.bitwiseTo(a,op_xor,r); return r; }\n\n // (public) this & ~a\n function op_andnot(x,y) { return x&~y; }\n function bnAndNot(a) { var r = nbi(); this.bitwiseTo(a,op_andnot,r); return r; }\n\n // (public) ~this\n function bnNot() {\n var r = nbi();\n for(var i = 0; i < this.t; ++i) r[i] = this.DM&~this[i];\n r.t = this.t;\n r.s = ~this.s;\n return r;\n }\n\n // (public) this << n\n function bnShiftLeft(n) {\n var r = nbi();\n if(n < 0) this.rShiftTo(-n,r); else this.lShiftTo(n,r);\n return r;\n }\n\n // (public) this >> n\n function bnShiftRight(n) {\n var r = nbi();\n if(n < 0) this.lShiftTo(-n,r); else this.rShiftTo(n,r);\n return r;\n }\n\n // return index of lowest 1-bit in x, x < 2^31\n function lbit(x) {\n if(x == 0) return -1;\n var r = 0;\n if((x&0xffff) == 0) { x >>= 16; r += 16; }\n if((x&0xff) == 0) { x >>= 8; r += 8; }\n if((x&0xf) == 0) { x >>= 4; r += 4; }\n if((x&3) == 0) { x >>= 2; r += 2; }\n if((x&1) == 0) ++r;\n return r;\n }\n\n // (public) returns index of lowest 1-bit (or -1 if none)\n function bnGetLowestSetBit() {\n for(var i = 0; i < this.t; ++i)\n if(this[i] != 0) return i*this.DB+lbit(this[i]);\n if(this.s < 0) return this.t*this.DB;\n return -1;\n }\n\n // return number of 1 bits in x\n function cbit(x) {\n var r = 0;\n while(x != 0) { x &= x-1; ++r; }\n return r;\n }\n\n // (public) return number of set bits\n function bnBitCount() {\n var r = 0, x = this.s&this.DM;\n for(var i = 0; i < this.t; ++i) r += cbit(this[i]^x);\n return r;\n }\n\n // (public) true iff nth bit is set\n function bnTestBit(n) {\n var j = Math.floor(n/this.DB);\n if(j >= this.t) return(this.s!=0);\n return((this[j]&(1<<(n%this.DB)))!=0);\n }\n\n // (protected) this op (1<<n)\n function bnpChangeBit(n,op) {\n var r = BigInteger.ONE.shiftLeft(n);\n this.bitwiseTo(r,op,r);\n return r;\n }\n\n // (public) this | (1<<n)\n function bnSetBit(n) { return this.changeBit(n,op_or); }\n\n // (public) this & ~(1<<n)\n function bnClearBit(n) { return this.changeBit(n,op_andnot); }\n\n // (public) this ^ (1<<n)\n function bnFlipBit(n) { return this.changeBit(n,op_xor); }\n\n // (protected) r = this + a\n function bnpAddTo(a,r) {\n var i = 0, c = 0, m = Math.min(a.t,this.t);\n while(i < m) {\n c += this[i]+a[i];\n r[i++] = c&this.DM;\n c >>= this.DB;\n }\n if(a.t < this.t) {\n c += a.s;\n while(i < this.t) {\n c += this[i];\n r[i++] = c&this.DM;\n c >>= this.DB;\n }\n c += this.s;\n }\n else {\n c += this.s;\n while(i < a.t) {\n c += a[i];\n r[i++] = c&this.DM;\n c >>= this.DB;\n }\n c += a.s;\n }\n r.s = (c<0)?-1:0;\n if(c > 0) r[i++] = c;\n else if(c < -1) r[i++] = this.DV+c;\n r.t = i;\n r.clamp();\n }\n\n // (public) this + a\n function bnAdd(a) { var r = nbi(); this.addTo(a,r); return r; }\n\n // (public) this - a\n function bnSubtract(a) { var r = nbi(); this.subTo(a,r); return r; }\n\n // (public) this * a\n function bnMultiply(a) { var r = nbi(); this.multiplyTo(a,r); return r; }\n\n // (public) this^2\n function bnSquare() { var r = nbi(); this.squareTo(r); return r; }\n\n // (public) this / a\n function bnDivide(a) { var r = nbi(); this.divRemTo(a,r,null); return r; }\n\n // (public) this % a\n function bnRemainder(a) { var r = nbi(); this.divRemTo(a,null,r); return r; }\n\n // (public) [this/a,this%a]\n function bnDivideAndRemainder(a) {\n var q = nbi(), r = nbi();\n this.divRemTo(a,q,r);\n return new Array(q,r);\n }\n\n // (protected) this *= n, this >= 0, 1 < n < DV\n function bnpDMultiply(n) {\n this[this.t] = this.am(0,n-1,this,0,0,this.t);\n ++this.t;\n this.clamp();\n }\n\n // (protected) this += n << w words, this >= 0\n function bnpDAddOffset(n,w) {\n if(n == 0) return;\n while(this.t <= w) this[this.t++] = 0;\n this[w] += n;\n while(this[w] >= this.DV) {\n this[w] -= this.DV;\n if(++w >= this.t) this[this.t++] = 0;\n ++this[w];\n }\n }\n\n // A \"null\" reducer\n function NullExp() {}\n function nNop(x) { return x; }\n function nMulTo(x,y,r) { x.multiplyTo(y,r); }\n function nSqrTo(x,r) { x.squareTo(r); }\n\n NullExp.prototype.convert = nNop;\n NullExp.prototype.revert = nNop;\n NullExp.prototype.mulTo = nMulTo;\n NullExp.prototype.sqrTo = nSqrTo;\n\n // (public) this^e\n function bnPow(e) { return this.exp(e,new NullExp()); }\n\n // (protected) r = lower n words of \"this * a\", a.t <= n\n // \"this\" should be the larger one if appropriate.\n function bnpMultiplyLowerTo(a,n,r) {\n var i = Math.min(this.t+a.t,n);\n r.s = 0; // assumes a,this >= 0\n r.t = i;\n while(i > 0) r[--i] = 0;\n var j;\n for(j = r.t-this.t; i < j; ++i) r[i+this.t] = this.am(0,a[i],r,i,0,this.t);\n for(j = Math.min(a.t,n); i < j; ++i) this.am(0,a[i],r,i,0,n-i);\n r.clamp();\n }\n\n // (protected) r = \"this * a\" without lower n words, n > 0\n // \"this\" should be the larger one if appropriate.\n function bnpMultiplyUpperTo(a,n,r) {\n --n;\n var i = r.t = this.t+a.t-n;\n r.s = 0; // assumes a,this >= 0\n while(--i >= 0) r[i] = 0;\n for(i = Math.max(n-this.t,0); i < a.t; ++i)\n r[this.t+i-n] = this.am(n-i,a[i],r,0,0,this.t+i-n);\n r.clamp();\n r.drShiftTo(1,r);\n }\n\n // Barrett modular reduction\n function Barrett(m) {\n // setup Barrett\n this.r2 = nbi();\n this.q3 = nbi();\n BigInteger.ONE.dlShiftTo(2*m.t,this.r2);\n this.mu = this.r2.divide(m);\n this.m = m;\n }\n\n function barrettConvert(x) {\n if(x.s < 0 || x.t > 2*this.m.t) return x.mod(this.m);\n else if(x.compareTo(this.m) < 0) return x;\n else { var r = nbi(); x.copyTo(r); this.reduce(r); return r; }\n }\n\n function barrettRevert(x) { return x; }\n\n // x = x mod m (HAC 14.42)\n function barrettReduce(x) {\n x.drShiftTo(this.m.t-1,this.r2);\n if(x.t > this.m.t+1) { x.t = this.m.t+1; x.clamp(); }\n this.mu.multiplyUpperTo(this.r2,this.m.t+1,this.q3);\n this.m.multiplyLowerTo(this.q3,this.m.t+1,this.r2);\n while(x.compareTo(this.r2) < 0) x.dAddOffset(1,this.m.t+1);\n x.subTo(this.r2,x);\n while(x.compareTo(this.m) >= 0) x.subTo(this.m,x);\n }\n\n // r = x^2 mod m; x != r\n function barrettSqrTo(x,r) { x.squareTo(r); this.reduce(r); }\n\n // r = x*y mod m; x,y != r\n function barrettMulTo(x,y,r) { x.multiplyTo(y,r); this.reduce(r); }\n\n Barrett.prototype.convert = barrettConvert;\n Barrett.prototype.revert = barrettRevert;\n Barrett.prototype.reduce = barrettReduce;\n Barrett.prototype.mulTo = barrettMulTo;\n Barrett.prototype.sqrTo = barrettSqrTo;\n\n // (public) this^e % m (HAC 14.85)\n function bnModPow(e,m) {\n var i = e.bitLength(), k, r = nbv(1), z;\n if(i <= 0) return r;\n else if(i < 18) k = 1;\n else if(i < 48) k = 3;\n else if(i < 144) k = 4;\n else if(i < 768) k = 5;\n else k = 6;\n if(i < 8)\n z = new Classic(m);\n else if(m.isEven())\n z = new Barrett(m);\n else\n z = new Montgomery(m);\n\n // precomputation\n var g = new Array(), n = 3, k1 = k-1, km = (1<<k)-1;\n g[1] = z.convert(this);\n if(k > 1) {\n var g2 = nbi();\n z.sqrTo(g[1],g2);\n while(n <= km) {\n g[n] = nbi();\n z.mulTo(g2,g[n-2],g[n]);\n n += 2;\n }\n }\n\n var j = e.t-1, w, is1 = true, r2 = nbi(), t;\n i = nbits(e[j])-1;\n while(j >= 0) {\n if(i >= k1) w = (e[j]>>(i-k1))&km;\n else {\n w = (e[j]&((1<<(i+1))-1))<<(k1-i);\n if(j > 0) w |= e[j-1]>>(this.DB+i-k1);\n }\n\n n = k;\n while((w&1) == 0) { w >>= 1; --n; }\n if((i -= n) < 0) { i += this.DB; --j; }\n if(is1) { // ret == 1, don't bother squaring or multiplying it\n g[w].copyTo(r);\n is1 = false;\n }\n else {\n while(n > 1) { z.sqrTo(r,r2); z.sqrTo(r2,r); n -= 2; }\n if(n > 0) z.sqrTo(r,r2); else { t = r; r = r2; r2 = t; }\n z.mulTo(r2,g[w],r);\n }\n\n while(j >= 0 && (e[j]&(1<<i)) == 0) {\n z.sqrTo(r,r2); t = r; r = r2; r2 = t;\n if(--i < 0) { i = this.DB-1; --j; }\n }\n }\n return z.revert(r);\n }\n\n // (public) gcd(this,a) (HAC 14.54)\n function bnGCD(a) {\n var x = (this.s<0)?this.negate():this.clone();\n var y = (a.s<0)?a.negate():a.clone();\n if(x.compareTo(y) < 0) { var t = x; x = y; y = t; }\n var i = x.getLowestSetBit(), g = y.getLowestSetBit();\n if(g < 0) return x;\n if(i < g) g = i;\n if(g > 0) {\n x.rShiftTo(g,x);\n y.rShiftTo(g,y);\n }\n while(x.signum() > 0) {\n if((i = x.getLowestSetBit()) > 0) x.rShiftTo(i,x);\n if((i = y.getLowestSetBit()) > 0) y.rShiftTo(i,y);\n if(x.compareTo(y) >= 0) {\n x.subTo(y,x);\n x.rShiftTo(1,x);\n }\n else {\n y.subTo(x,y);\n y.rShiftTo(1,y);\n }\n }\n if(g > 0) y.lShiftTo(g,y);\n return y;\n }\n\n // (protected) this % n, n < 2^26\n function bnpModInt(n) {\n if(n <= 0) return 0;\n var d = this.DV%n, r = (this.s<0)?n-1:0;\n if(this.t > 0)\n if(d == 0) r = this[0]%n;\n else for(var i = this.t-1; i >= 0; --i) r = (d*r+this[i])%n;\n return r;\n }\n\n // (public) 1/this % m (HAC 14.61)\n function bnModInverse(m) {\n var ac = m.isEven();\n if((this.isEven() && ac) || m.signum() == 0) return BigInteger.ZERO;\n var u = m.clone(), v = this.clone();\n var a = nbv(1), b = nbv(0), c = nbv(0), d = nbv(1);\n while(u.signum() != 0) {\n while(u.isEven()) {\n u.rShiftTo(1,u);\n if(ac) {\n if(!a.isEven() || !b.isEven()) { a.addTo(this,a); b.subTo(m,b); }\n a.rShiftTo(1,a);\n }\n else if(!b.isEven()) b.subTo(m,b);\n b.rShiftTo(1,b);\n }\n while(v.isEven()) {\n v.rShiftTo(1,v);\n if(ac) {\n if(!c.isEven() || !d.isEven()) { c.addTo(this,c); d.subTo(m,d); }\n c.rShiftTo(1,c);\n }\n else if(!d.isEven()) d.subTo(m,d);\n d.rShiftTo(1,d);\n }\n if(u.compareTo(v) >= 0) {\n u.subTo(v,u);\n if(ac) a.subTo(c,a);\n b.subTo(d,b);\n }\n else {\n v.subTo(u,v);\n if(ac) c.subTo(a,c);\n d.subTo(b,d);\n }\n }\n if(v.compareTo(BigInteger.ONE) != 0) return BigInteger.ZERO;\n if(d.compareTo(m) >= 0) return d.subtract(m);\n if(d.signum() < 0) d.addTo(m,d); else return d;\n if(d.signum() < 0) return d.add(m); else return d;\n }\n\n var lowprimes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293,307,311,313,317,331,337,347,349,353,359,367,373,379,383,389,397,401,409,419,421,431,433,439,443,449,457,461,463,467,479,487,491,499,503,509,521,523,541,547,557,563,569,571,577,587,593,599,601,607,613,617,619,631,641,643,647,653,659,661,673,677,683,691,701,709,719,727,733,739,743,751,757,761,769,773,787,797,809,811,821,823,827,829,839,853,857,859,863,877,881,883,887,907,911,919,929,937,941,947,953,967,971,977,983,991,997];\n var lplim = (1<<26)/lowprimes[lowprimes.length-1];\n\n // (public) test primality with certainty >= 1-.5^t\n function bnIsProbablePrime(t) {\n var i, x = this.abs();\n if(x.t == 1 && x[0] <= lowprimes[lowprimes.length-1]) {\n for(i = 0; i < lowprimes.length; ++i)\n if(x[0] == lowprimes[i]) return true;\n return false;\n }\n if(x.isEven()) return false;\n i = 1;\n while(i < lowprimes.length) {\n var m = lowprimes[i], j = i+1;\n while(j < lowprimes.length && m < lplim) m *= lowprimes[j++];\n m = x.modInt(m);\n while(i < j) if(m%lowprimes[i++] == 0) return false;\n }\n return x.millerRabin(t);\n }\n\n // (protected) true if probably prime (HAC 4.24, Miller-Rabin)\n function bnpMillerRabin(t) {\n var n1 = this.subtract(BigInteger.ONE);\n var k = n1.getLowestSetBit();\n if(k <= 0) return false;\n var r = n1.shiftRight(k);\n t = (t+1)>>1;\n if(t > lowprimes.length) t = lowprimes.length;\n var a = nbi();\n for(var i = 0; i < t; ++i) {\n //Pick bases at random, instead of starting at 2\n a.fromInt(lowprimes[Math.floor(Math.random()*lowprimes.length)]);\n var y = a.modPow(r,this);\n if(y.compareTo(BigInteger.ONE) != 0 && y.compareTo(n1) != 0) {\n var j = 1;\n while(j++ < k && y.compareTo(n1) != 0) {\n y = y.modPowInt(2,this);\n if(y.compareTo(BigInteger.ONE) == 0) return false;\n }\n if(y.compareTo(n1) != 0) return false;\n }\n }\n return true;\n }\n\n // protected\n BigInteger.prototype.chunkSize = bnpChunkSize;\n BigInteger.prototype.toRadix = bnpToRadix;\n BigInteger.prototype.fromRadix = bnpFromRadix;\n BigInteger.prototype.fromNumber = bnpFromNumber;\n BigInteger.prototype.bitwiseTo = bnpBitwiseTo;\n BigInteger.prototype.changeBit = bnpChangeBit;\n BigInteger.prototype.addTo = bnpAddTo;\n BigInteger.prototype.dMultiply = bnpDMultiply;\n BigInteger.prototype.dAddOffset = bnpDAddOffset;\n BigInteger.prototype.multiplyLowerTo = bnpMultiplyLowerTo;\n BigInteger.prototype.multiplyUpperTo = bnpMultiplyUpperTo;\n BigInteger.prototype.modInt = bnpModInt;\n BigInteger.prototype.millerRabin = bnpMillerRabin;\n\n // public\n BigInteger.prototype.clone = bnClone;\n BigInteger.prototype.intValue = bnIntValue;\n BigInteger.prototype.byteValue = bnByteValue;\n BigInteger.prototype.shortValue = bnShortValue;\n BigInteger.prototype.signum = bnSigNum;\n BigInteger.prototype.toByteArray = bnToByteArray;\n BigInteger.prototype.equals = bnEquals;\n BigInteger.prototype.min = bnMin;\n BigInteger.prototype.max = bnMax;\n BigInteger.prototype.and = bnAnd;\n BigInteger.prototype.or = bnOr;\n BigInteger.prototype.xor = bnXor;\n BigInteger.prototype.andNot = bnAndNot;\n BigInteger.prototype.not = bnNot;\n BigInteger.prototype.shiftLeft = bnShiftLeft;\n BigInteger.prototype.shiftRight = bnShiftRight;\n BigInteger.prototype.getLowestSetBit = bnGetLowestSetBit;\n BigInteger.prototype.bitCount = bnBitCount;\n BigInteger.prototype.testBit = bnTestBit;\n BigInteger.prototype.setBit = bnSetBit;\n BigInteger.prototype.clearBit = bnClearBit;\n BigInteger.prototype.flipBit = bnFlipBit;\n BigInteger.prototype.add = bnAdd;\n BigInteger.prototype.subtract = bnSubtract;\n BigInteger.prototype.multiply = bnMultiply;\n BigInteger.prototype.divide = bnDivide;\n BigInteger.prototype.remainder = bnRemainder;\n BigInteger.prototype.divideAndRemainder = bnDivideAndRemainder;\n BigInteger.prototype.modPow = bnModPow;\n BigInteger.prototype.modInverse = bnModInverse;\n BigInteger.prototype.pow = bnPow;\n BigInteger.prototype.gcd = bnGCD;\n BigInteger.prototype.isProbablePrime = bnIsProbablePrime;\n\n // JSBN-specific extension\n BigInteger.prototype.square = bnSquare;\n\n // Expose the Barrett function\n BigInteger.prototype.Barrett = Barrett\n\n // BigInteger interfaces not implemented in jsbn:\n\n // BigInteger(int signum, byte[] magnitude)\n // double doubleValue()\n // float floatValue()\n // int hashCode()\n // long longValue()\n // static BigInteger valueOf(long val)\n\n // Random number generator - requires a PRNG backend, e.g. prng4.js\n\n // For best results, put code like\n // <body onClick='rng_seed_time();' onKeyPress='rng_seed_time();'>\n // in your main HTML document.\n\n var rng_state;\n var rng_pool;\n var rng_pptr;\n\n // Mix in a 32-bit integer into the pool\n function rng_seed_int(x) {\n rng_pool[rng_pptr++] ^= x & 255;\n rng_pool[rng_pptr++] ^= (x >> 8) & 255;\n rng_pool[rng_pptr++] ^= (x >> 16) & 255;\n rng_pool[rng_pptr++] ^= (x >> 24) & 255;\n if(rng_pptr >= rng_psize) rng_pptr -= rng_psize;\n }\n\n // Mix in the current time (w/milliseconds) into the pool\n function rng_seed_time() {\n rng_seed_int(new Date().getTime());\n }\n\n // Initialize the pool with junk if needed.\n if(rng_pool == null) {\n rng_pool = new Array();\n rng_pptr = 0;\n var t;\n if(typeof window !== \"undefined\" && window.crypto) {\n if (window.crypto.getRandomValues) {\n // Use webcrypto if available\n var ua = new Uint8Array(32);\n window.crypto.getRandomValues(ua);\n for(t = 0; t < 32; ++t)\n rng_pool[rng_pptr++] = ua[t];\n }\n else if(navigator.appName == \"Netscape\" && navigator.appVersion < \"5\") {\n // Extract entropy (256 bits) from NS4 RNG if available\n var z = window.crypto.random(32);\n for(t = 0; t < z.length; ++t)\n rng_pool[rng_pptr++] = z.charCodeAt(t) & 255;\n }\n }\n while(rng_pptr < rng_psize) { // extract some randomness from Math.random()\n t = Math.floor(65536 * Math.random());\n rng_pool[rng_pptr++] = t >>> 8;\n rng_pool[rng_pptr++] = t & 255;\n }\n rng_pptr = 0;\n rng_seed_time();\n //rng_seed_int(window.screenX);\n //rng_seed_int(window.screenY);\n }\n\n function rng_get_byte() {\n if(rng_state == null) {\n rng_seed_time();\n rng_state = prng_newstate();\n rng_state.init(rng_pool);\n for(rng_pptr = 0; rng_pptr < rng_pool.length; ++rng_pptr)\n rng_pool[rng_pptr] = 0;\n rng_pptr = 0;\n //rng_pool = null;\n }\n // TODO: allow reseeding after first request\n return rng_state.next();\n }\n\n function rng_get_bytes(ba) {\n var i;\n for(i = 0; i < ba.length; ++i) ba[i] = rng_get_byte();\n }\n\n function SecureRandom() {}\n\n SecureRandom.prototype.nextBytes = rng_get_bytes;\n\n // prng4.js - uses Arcfour as a PRNG\n\n function Arcfour() {\n this.i = 0;\n this.j = 0;\n this.S = new Array();\n }\n\n // Initialize arcfour context from key, an array of ints, each from [0..255]\n function ARC4init(key) {\n var i, j, t;\n for(i = 0; i < 256; ++i)\n this.S[i] = i;\n j = 0;\n for(i = 0; i < 256; ++i) {\n j = (j + this.S[i] + key[i % key.length]) & 255;\n t = this.S[i];\n this.S[i] = this.S[j];\n this.S[j] = t;\n }\n this.i = 0;\n this.j = 0;\n }\n\n function ARC4next() {\n var t;\n this.i = (this.i + 1) & 255;\n this.j = (this.j + this.S[this.i]) & 255;\n t = this.S[this.i];\n this.S[this.i] = this.S[this.j];\n this.S[this.j] = t;\n return this.S[(t + this.S[this.i]) & 255];\n }\n\n Arcfour.prototype.init = ARC4init;\n Arcfour.prototype.next = ARC4next;\n\n // Plug in your RNG constructor here\n function prng_newstate() {\n return new Arcfour();\n }\n\n // Pool size must be a multiple of 4 and greater than 32.\n // An array of bytes the size of the pool will be passed to init()\n var rng_psize = 256;\n\n if (typeof exports !== 'undefined') {\n exports = module.exports = {\n default: BigInteger,\n BigInteger: BigInteger,\n SecureRandom: SecureRandom,\n };\n } else {\n this.jsbn = {\n BigInteger: BigInteger,\n SecureRandom: SecureRandom\n };\n }\n\n}).call(this);\n"]}
\ No newline at end of file
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921836, function(require, module, exports) {
(function(){
var crypt = require('crypt'),
utf8 = require('charenc').utf8,
isBuffer = require('is-buffer'),
bin = require('charenc').bin,
// The core
md5 = function (message, options) {
// Convert to byte array
if (message.constructor == String)
if (options && options.encoding === 'binary')
message = bin.stringToBytes(message);
else
message = utf8.stringToBytes(message);
else if (isBuffer(message))
message = Array.prototype.slice.call(message, 0);
else if (!Array.isArray(message) && message.constructor !== Uint8Array)
message = message.toString();
// else, assume byte array already
var m = crypt.bytesToWords(message),
l = message.length * 8,
a = 1732584193,
b = -271733879,
c = -1732584194,
d = 271733878;
// Swap endian
for (var i = 0; i < m.length; i++) {
m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |
((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;
}
// Padding
m[l >>> 5] |= 0x80 << (l % 32);
m[(((l + 64) >>> 9) << 4) + 14] = l;
// Method shortcuts
var FF = md5._ff,
GG = md5._gg,
HH = md5._hh,
II = md5._ii;
for (var i = 0; i < m.length; i += 16) {
var aa = a,
bb = b,
cc = c,
dd = d;
a = FF(a, b, c, d, m[i+ 0], 7, -680876936);
d = FF(d, a, b, c, m[i+ 1], 12, -389564586);
c = FF(c, d, a, b, m[i+ 2], 17, 606105819);
b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);
a = FF(a, b, c, d, m[i+ 4], 7, -176418897);
d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);
c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);
b = FF(b, c, d, a, m[i+ 7], 22, -45705983);
a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);
d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);
c = FF(c, d, a, b, m[i+10], 17, -42063);
b = FF(b, c, d, a, m[i+11], 22, -1990404162);
a = FF(a, b, c, d, m[i+12], 7, 1804603682);
d = FF(d, a, b, c, m[i+13], 12, -40341101);
c = FF(c, d, a, b, m[i+14], 17, -1502002290);
b = FF(b, c, d, a, m[i+15], 22, 1236535329);
a = GG(a, b, c, d, m[i+ 1], 5, -165796510);
d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);
c = GG(c, d, a, b, m[i+11], 14, 643717713);
b = GG(b, c, d, a, m[i+ 0], 20, -373897302);
a = GG(a, b, c, d, m[i+ 5], 5, -701558691);
d = GG(d, a, b, c, m[i+10], 9, 38016083);
c = GG(c, d, a, b, m[i+15], 14, -660478335);
b = GG(b, c, d, a, m[i+ 4], 20, -405537848);
a = GG(a, b, c, d, m[i+ 9], 5, 568446438);
d = GG(d, a, b, c, m[i+14], 9, -1019803690);
c = GG(c, d, a, b, m[i+ 3], 14, -187363961);
b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);
a = GG(a, b, c, d, m[i+13], 5, -1444681467);
d = GG(d, a, b, c, m[i+ 2], 9, -51403784);
c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);
b = GG(b, c, d, a, m[i+12], 20, -1926607734);
a = HH(a, b, c, d, m[i+ 5], 4, -378558);
d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);
c = HH(c, d, a, b, m[i+11], 16, 1839030562);
b = HH(b, c, d, a, m[i+14], 23, -35309556);
a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);
d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);
c = HH(c, d, a, b, m[i+ 7], 16, -155497632);
b = HH(b, c, d, a, m[i+10], 23, -1094730640);
a = HH(a, b, c, d, m[i+13], 4, 681279174);
d = HH(d, a, b, c, m[i+ 0], 11, -358537222);
c = HH(c, d, a, b, m[i+ 3], 16, -722521979);
b = HH(b, c, d, a, m[i+ 6], 23, 76029189);
a = HH(a, b, c, d, m[i+ 9], 4, -640364487);
d = HH(d, a, b, c, m[i+12], 11, -421815835);
c = HH(c, d, a, b, m[i+15], 16, 530742520);
b = HH(b, c, d, a, m[i+ 2], 23, -995338651);
a = II(a, b, c, d, m[i+ 0], 6, -198630844);
d = II(d, a, b, c, m[i+ 7], 10, 1126891415);
c = II(c, d, a, b, m[i+14], 15, -1416354905);
b = II(b, c, d, a, m[i+ 5], 21, -57434055);
a = II(a, b, c, d, m[i+12], 6, 1700485571);
d = II(d, a, b, c, m[i+ 3], 10, -1894986606);
c = II(c, d, a, b, m[i+10], 15, -1051523);
b = II(b, c, d, a, m[i+ 1], 21, -2054922799);
a = II(a, b, c, d, m[i+ 8], 6, 1873313359);
d = II(d, a, b, c, m[i+15], 10, -30611744);
c = II(c, d, a, b, m[i+ 6], 15, -1560198380);
b = II(b, c, d, a, m[i+13], 21, 1309151649);
a = II(a, b, c, d, m[i+ 4], 6, -145523070);
d = II(d, a, b, c, m[i+11], 10, -1120210379);
c = II(c, d, a, b, m[i+ 2], 15, 718787259);
b = II(b, c, d, a, m[i+ 9], 21, -343485551);
a = (a + aa) >>> 0;
b = (b + bb) >>> 0;
c = (c + cc) >>> 0;
d = (d + dd) >>> 0;
}
return crypt.endian([a, b, c, d]);
};
// Auxiliary functions
md5._ff = function (a, b, c, d, x, s, t) {
var n = a + (b & c | ~b & d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._gg = function (a, b, c, d, x, s, t) {
var n = a + (b & d | c & ~d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._hh = function (a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
md5._ii = function (a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;
return ((n << s) | (n >>> (32 - s))) + b;
};
// Package private blocksize
md5._blocksize = 16;
md5._digestsize = 16;
module.exports = function (message, options) {
if (message === undefined || message === null)
throw new Error('Illegal argument ' + message);
var digestbytes = crypt.wordsToBytes(md5(message, options));
return options && options.asBytes ? digestbytes :
options && options.asString ? bin.bytesToString(digestbytes) :
crypt.bytesToHex(digestbytes);
};
})();
}, function(modId) {var map = {}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921836);
})()
//miniprogram-npm-outsideDeps=["crypt","charenc","is-buffer"]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["md5.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["(function(){\r\n var crypt = require('crypt'),\r\n utf8 = require('charenc').utf8,\r\n isBuffer = require('is-buffer'),\r\n bin = require('charenc').bin,\r\n\r\n // The core\r\n md5 = function (message, options) {\r\n // Convert to byte array\r\n if (message.constructor == String)\r\n if (options && options.encoding === 'binary')\r\n message = bin.stringToBytes(message);\r\n else\r\n message = utf8.stringToBytes(message);\r\n else if (isBuffer(message))\r\n message = Array.prototype.slice.call(message, 0);\r\n else if (!Array.isArray(message) && message.constructor !== Uint8Array)\r\n message = message.toString();\r\n // else, assume byte array already\r\n\r\n var m = crypt.bytesToWords(message),\r\n l = message.length * 8,\r\n a = 1732584193,\r\n b = -271733879,\r\n c = -1732584194,\r\n d = 271733878;\r\n\r\n // Swap endian\r\n for (var i = 0; i < m.length; i++) {\r\n m[i] = ((m[i] << 8) | (m[i] >>> 24)) & 0x00FF00FF |\r\n ((m[i] << 24) | (m[i] >>> 8)) & 0xFF00FF00;\r\n }\r\n\r\n // Padding\r\n m[l >>> 5] |= 0x80 << (l % 32);\r\n m[(((l + 64) >>> 9) << 4) + 14] = l;\r\n\r\n // Method shortcuts\r\n var FF = md5._ff,\r\n GG = md5._gg,\r\n HH = md5._hh,\r\n II = md5._ii;\r\n\r\n for (var i = 0; i < m.length; i += 16) {\r\n\r\n var aa = a,\r\n bb = b,\r\n cc = c,\r\n dd = d;\r\n\r\n a = FF(a, b, c, d, m[i+ 0], 7, -680876936);\r\n d = FF(d, a, b, c, m[i+ 1], 12, -389564586);\r\n c = FF(c, d, a, b, m[i+ 2], 17, 606105819);\r\n b = FF(b, c, d, a, m[i+ 3], 22, -1044525330);\r\n a = FF(a, b, c, d, m[i+ 4], 7, -176418897);\r\n d = FF(d, a, b, c, m[i+ 5], 12, 1200080426);\r\n c = FF(c, d, a, b, m[i+ 6], 17, -1473231341);\r\n b = FF(b, c, d, a, m[i+ 7], 22, -45705983);\r\n a = FF(a, b, c, d, m[i+ 8], 7, 1770035416);\r\n d = FF(d, a, b, c, m[i+ 9], 12, -1958414417);\r\n c = FF(c, d, a, b, m[i+10], 17, -42063);\r\n b = FF(b, c, d, a, m[i+11], 22, -1990404162);\r\n a = FF(a, b, c, d, m[i+12], 7, 1804603682);\r\n d = FF(d, a, b, c, m[i+13], 12, -40341101);\r\n c = FF(c, d, a, b, m[i+14], 17, -1502002290);\r\n b = FF(b, c, d, a, m[i+15], 22, 1236535329);\r\n\r\n a = GG(a, b, c, d, m[i+ 1], 5, -165796510);\r\n d = GG(d, a, b, c, m[i+ 6], 9, -1069501632);\r\n c = GG(c, d, a, b, m[i+11], 14, 643717713);\r\n b = GG(b, c, d, a, m[i+ 0], 20, -373897302);\r\n a = GG(a, b, c, d, m[i+ 5], 5, -701558691);\r\n d = GG(d, a, b, c, m[i+10], 9, 38016083);\r\n c = GG(c, d, a, b, m[i+15], 14, -660478335);\r\n b = GG(b, c, d, a, m[i+ 4], 20, -405537848);\r\n a = GG(a, b, c, d, m[i+ 9], 5, 568446438);\r\n d = GG(d, a, b, c, m[i+14], 9, -1019803690);\r\n c = GG(c, d, a, b, m[i+ 3], 14, -187363961);\r\n b = GG(b, c, d, a, m[i+ 8], 20, 1163531501);\r\n a = GG(a, b, c, d, m[i+13], 5, -1444681467);\r\n d = GG(d, a, b, c, m[i+ 2], 9, -51403784);\r\n c = GG(c, d, a, b, m[i+ 7], 14, 1735328473);\r\n b = GG(b, c, d, a, m[i+12], 20, -1926607734);\r\n\r\n a = HH(a, b, c, d, m[i+ 5], 4, -378558);\r\n d = HH(d, a, b, c, m[i+ 8], 11, -2022574463);\r\n c = HH(c, d, a, b, m[i+11], 16, 1839030562);\r\n b = HH(b, c, d, a, m[i+14], 23, -35309556);\r\n a = HH(a, b, c, d, m[i+ 1], 4, -1530992060);\r\n d = HH(d, a, b, c, m[i+ 4], 11, 1272893353);\r\n c = HH(c, d, a, b, m[i+ 7], 16, -155497632);\r\n b = HH(b, c, d, a, m[i+10], 23, -1094730640);\r\n a = HH(a, b, c, d, m[i+13], 4, 681279174);\r\n d = HH(d, a, b, c, m[i+ 0], 11, -358537222);\r\n c = HH(c, d, a, b, m[i+ 3], 16, -722521979);\r\n b = HH(b, c, d, a, m[i+ 6], 23, 76029189);\r\n a = HH(a, b, c, d, m[i+ 9], 4, -640364487);\r\n d = HH(d, a, b, c, m[i+12], 11, -421815835);\r\n c = HH(c, d, a, b, m[i+15], 16, 530742520);\r\n b = HH(b, c, d, a, m[i+ 2], 23, -995338651);\r\n\r\n a = II(a, b, c, d, m[i+ 0], 6, -198630844);\r\n d = II(d, a, b, c, m[i+ 7], 10, 1126891415);\r\n c = II(c, d, a, b, m[i+14], 15, -1416354905);\r\n b = II(b, c, d, a, m[i+ 5], 21, -57434055);\r\n a = II(a, b, c, d, m[i+12], 6, 1700485571);\r\n d = II(d, a, b, c, m[i+ 3], 10, -1894986606);\r\n c = II(c, d, a, b, m[i+10], 15, -1051523);\r\n b = II(b, c, d, a, m[i+ 1], 21, -2054922799);\r\n a = II(a, b, c, d, m[i+ 8], 6, 1873313359);\r\n d = II(d, a, b, c, m[i+15], 10, -30611744);\r\n c = II(c, d, a, b, m[i+ 6], 15, -1560198380);\r\n b = II(b, c, d, a, m[i+13], 21, 1309151649);\r\n a = II(a, b, c, d, m[i+ 4], 6, -145523070);\r\n d = II(d, a, b, c, m[i+11], 10, -1120210379);\r\n c = II(c, d, a, b, m[i+ 2], 15, 718787259);\r\n b = II(b, c, d, a, m[i+ 9], 21, -343485551);\r\n\r\n a = (a + aa) >>> 0;\r\n b = (b + bb) >>> 0;\r\n c = (c + cc) >>> 0;\r\n d = (d + dd) >>> 0;\r\n }\r\n\r\n return crypt.endian([a, b, c, d]);\r\n };\r\n\r\n // Auxiliary functions\r\n md5._ff = function (a, b, c, d, x, s, t) {\r\n var n = a + (b & c | ~b & d) + (x >>> 0) + t;\r\n return ((n << s) | (n >>> (32 - s))) + b;\r\n };\r\n md5._gg = function (a, b, c, d, x, s, t) {\r\n var n = a + (b & d | c & ~d) + (x >>> 0) + t;\r\n return ((n << s) | (n >>> (32 - s))) + b;\r\n };\r\n md5._hh = function (a, b, c, d, x, s, t) {\r\n var n = a + (b ^ c ^ d) + (x >>> 0) + t;\r\n return ((n << s) | (n >>> (32 - s))) + b;\r\n };\r\n md5._ii = function (a, b, c, d, x, s, t) {\r\n var n = a + (c ^ (b | ~d)) + (x >>> 0) + t;\r\n return ((n << s) | (n >>> (32 - s))) + b;\r\n };\r\n\r\n // Package private blocksize\r\n md5._blocksize = 16;\r\n md5._digestsize = 16;\r\n\r\n module.exports = function (message, options) {\r\n if (message === undefined || message === null)\r\n throw new Error('Illegal argument ' + message);\r\n\r\n var digestbytes = crypt.wordsToBytes(md5(message, options));\r\n return options && options.asBytes ? digestbytes :\r\n options && options.asString ? bin.bytesToString(digestbytes) :\r\n crypt.bytesToHex(digestbytes);\r\n };\r\n\r\n})();\r\n"]}
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
module.exports = (function() {
var __MODS__ = {};
var __DEFINE__ = function(modId, func, req) { var m = { exports: {}, _tempexports: {} }; __MODS__[modId] = { status: 0, func: func, req: req, m: m }; };
var __REQUIRE__ = function(modId, source) { if(!__MODS__[modId]) return require(source); if(!__MODS__[modId].status) { var m = __MODS__[modId].m; m._exports = m._tempexports; var desp = Object.getOwnPropertyDescriptor(m, "exports"); if (desp && desp.configurable) Object.defineProperty(m, "exports", { set: function (val) { if(typeof val === "object" && val !== m._exports) { m._exports.__proto__ = val.__proto__; Object.keys(val).forEach(function (k) { m._exports[k] = val[k]; }); } m._tempexports = val }, get: function () { return m._tempexports; } }); __MODS__[modId].status = 1; __MODS__[modId].func(__MODS__[modId].req, m, m.exports); } return __MODS__[modId].m.exports; };
var __REQUIRE_WILDCARD__ = function(obj) { if(obj && obj.__esModule) { return obj; } else { var newObj = {}; if(obj != null) { for(var k in obj) { if (Object.prototype.hasOwnProperty.call(obj, k)) newObj[k] = obj[k]; } } newObj.default = obj; return newObj; } };
var __REQUIRE_DEFAULT__ = function(obj) { return obj && obj.__esModule ? obj.default : obj; };
__DEFINE__(1743039921838, function(require, module, exports) {
module.exports = {
sm2: require('./sm2/index'),
sm3: require('./sm3/index'),
sm4: require('./sm4/index'),
}
}, function(modId) {var map = {"./sm2/index":1743039921839,"./sm3/index":1743039921844,"./sm4/index":1743039921845}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921839, function(require, module, exports) {
/* eslint-disable no-use-before-define */
const {BigInteger} = require('jsbn')
const {encodeDer, decodeDer} = require('./asn1')
const _ = require('./utils')
const sm3 = require('./sm3').sm3
const {G, curve, n} = _.generateEcparam()
const C1C2C3 = 0
/**
* 加密
*/
function doEncrypt(msg, publicKey, cipherMode = 1) {
msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg)
publicKey = _.getGlobalCurve().decodePointHex(publicKey) // 先将公钥转成点
const keypair = _.generateKeyPairHex()
const k = new BigInteger(keypair.privateKey, 16) // 随机数 k
// c1 = k * G
let c1 = keypair.publicKey
if (c1.length > 128) c1 = c1.substr(c1.length - 128)
// (x2, y2) = k * publicKey
const p = publicKey.multiply(k)
const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
// c3 = hash(x2 || msg || y2)
const c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
let ct = 1
let offset = 0
let t = [] // 256 位
const z = [].concat(x2, y2)
const nextT = () => {
// (1) Hai = hash(z || ct)
// (2) ct++
t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
ct++
offset = 0
}
nextT() // 先生成 Ha1
for (let i = 0, len = msg.length; i < len; i++) {
// t = Ha1 || Ha2 || Ha3 || Ha4
if (offset === t.length) nextT()
// c2 = msg ^ t
msg[i] ^= t[offset++] & 0xff
}
const c2 = _.arrayToHex(msg)
return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2
}
/**
* 解密
*/
function doDecrypt(encryptData, privateKey, cipherMode = 1, {
output = 'string',
} = {}) {
privateKey = new BigInteger(privateKey, 16)
let c3 = encryptData.substr(128, 64)
let c2 = encryptData.substr(128 + 64)
if (cipherMode === C1C2C3) {
c3 = encryptData.substr(encryptData.length - 64)
c2 = encryptData.substr(128, encryptData.length - 128 - 64)
}
const msg = _.hexToArray(c2)
const c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128))
const p = c1.multiply(privateKey)
const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))
const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))
let ct = 1
let offset = 0
let t = [] // 256 位
const z = [].concat(x2, y2)
const nextT = () => {
// (1) Hai = hash(z || ct)
// (2) ct++
t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])
ct++
offset = 0
}
nextT() // 先生成 Ha1
for (let i = 0, len = msg.length; i < len; i++) {
// t = Ha1 || Ha2 || Ha3 || Ha4
if (offset === t.length) nextT()
// c2 = msg ^ t
msg[i] ^= t[offset++] & 0xff
}
// c3 = hash(x2 || msg || y2)
const checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))
if (checkC3 === c3.toLowerCase()) {
return output === 'array' ? msg : _.arrayToUtf8(msg)
} else {
return output === 'array' ? [] : ''
}
}
/**
* 签名
*/
function doSignature(msg, privateKey, {
pointPool, der, hash, publicKey, userId
} = {}) {
let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
if (hash) {
// sm3杂凑
publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)
hashHex = getHash(hashHex, publicKey, userId)
}
const dA = new BigInteger(privateKey, 16)
const e = new BigInteger(hashHex, 16)
// k
let k = null
let r = null
let s = null
do {
do {
let point
if (pointPool && pointPool.length) {
point = pointPool.pop()
} else {
point = getPoint()
}
k = point.k
// r = (e + x1) mod n
r = e.add(point.x1).mod(n)
} while (r.equals(BigInteger.ZERO) || r.add(k).equals(n))
// s = ((1 + dA)^-1 * (k - r * dA)) mod n
s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n)
} while (s.equals(BigInteger.ZERO))
if (der) return encodeDer(r, s) // asn.1 der 编码
return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64)
}
/**
* 验签
*/
function doVerifySignature(msg, signHex, publicKey, {der, hash, userId} = {}) {
let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)
if (hash) {
// sm3杂凑
hashHex = getHash(hashHex, publicKey, userId)
}
let r; let
s
if (der) {
const decodeDerObj = decodeDer(signHex) // asn.1 der 解码
r = decodeDerObj.r
s = decodeDerObj.s
} else {
r = new BigInteger(signHex.substring(0, 64), 16)
s = new BigInteger(signHex.substring(64), 16)
}
const PA = curve.decodePointHex(publicKey)
const e = new BigInteger(hashHex, 16)
// t = (r + s) mod n
const t = r.add(s).mod(n)
if (t.equals(BigInteger.ZERO)) return false
// x1y1 = s * G + t * PA
const x1y1 = G.multiply(s).add(PA.multiply(t))
// R = (e + x1) mod n
const R = e.add(x1y1.getX().toBigInteger()).mod(n)
return r.equals(R)
}
/**
* sm3杂凑算法
*/
function getHash(hashHex, publicKey, userId = '1234567812345678') {
// z = hash(entl || userId || a || b || gx || gy || px || py)
userId = _.utf8ToHex(userId)
const a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64)
const b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64)
const gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64)
const gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64)
let px
let py
if (publicKey.length === 128) {
px = publicKey.substr(0, 64)
py = publicKey.substr(64, 64)
} else {
const point = G.curve.decodePointHex(publicKey)
px = _.leftPad(point.getX().toBigInteger().toRadix(16), 64)
py = _.leftPad(point.getY().toBigInteger().toRadix(16), 64)
}
const data = _.hexToArray(userId + a + b + gx + gy + px + py)
const entl = userId.length * 4
data.unshift(entl & 0x00ff)
data.unshift(entl >> 8 & 0x00ff)
const z = sm3(data)
// e = hash(z || msg)
return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))))
}
/**
* 计算公钥
*/
function getPublicKeyFromPrivateKey(privateKey) {
const PA = G.multiply(new BigInteger(privateKey, 16))
const x = _.leftPad(PA.getX().toBigInteger().toString(16), 64)
const y = _.leftPad(PA.getY().toBigInteger().toString(16), 64)
return '04' + x + y
}
/**
* 获取椭圆曲线点
*/
function getPoint() {
const keypair = _.generateKeyPairHex()
const PA = curve.decodePointHex(keypair.publicKey)
keypair.k = new BigInteger(keypair.privateKey, 16)
keypair.x1 = PA.getX().toBigInteger()
return keypair
}
module.exports = {
generateKeyPairHex: _.generateKeyPairHex,
compressPublicKeyHex: _.compressPublicKeyHex,
comparePublicKeyHex: _.comparePublicKeyHex,
doEncrypt,
doDecrypt,
doSignature,
doVerifySignature,
getPublicKeyFromPrivateKey,
getPoint,
verifyPublicKey: _.verifyPublicKey,
}
}, function(modId) { var map = {"./asn1":1743039921840,"./utils":1743039921841,"./sm3":1743039921843}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921840, function(require, module, exports) {
/* eslint-disable class-methods-use-this */
const {BigInteger} = require('jsbn')
function bigintToValue(bigint) {
let h = bigint.toString(16)
if (h[0] !== '-') {
// 正数
if (h.length % 2 === 1) h = '0' + h // 补齐到整字节
else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节
} else {
// 负数
h = h.substr(1)
let len = h.length
if (len % 2 === 1) len += 1 // 补齐到整字节
else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节
let mask = ''
for (let i = 0; i < len; i++) mask += 'f'
mask = new BigInteger(mask, 16)
// 对绝对值取反,加1
h = mask.xor(bigint).add(BigInteger.ONE)
h = h.toString(16).replace(/^-/, '')
}
return h
}
class ASN1Object {
constructor() {
this.tlv = null
this.t = '00'
this.l = '00'
this.v = ''
}
/**
* 获取 der 编码比特流16进制串
*/
getEncodedHex() {
if (!this.tlv) {
this.v = this.getValue()
this.l = this.getLength()
this.tlv = this.t + this.l + this.v
}
return this.tlv
}
getLength() {
const n = this.v.length / 2 // 字节数
let nHex = n.toString(16)
if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节
if (n < 128) {
// 短格式,以 0 开头
return nHex
} else {
// 长格式,以 1 开头
const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度
return head.toString(16) + nHex
}
}
getValue() {
return ''
}
}
class DERInteger extends ASN1Object {
constructor(bigint) {
super()
this.t = '02' // 整型标签说明
if (bigint) this.v = bigintToValue(bigint)
}
getValue() {
return this.v
}
}
class DERSequence extends ASN1Object {
constructor(asn1Array) {
super()
this.t = '30' // 序列标签说明
this.asn1Array = asn1Array
}
getValue() {
this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')
return this.v
}
}
/**
* 获取 l 占用字节数
*/
function getLenOfL(str, start) {
if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节
return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身
}
/**
* 获取 l
*/
function getL(str, start) {
// 获取 l
const len = getLenOfL(str, start)
const l = str.substr(start + 2, len * 2)
if (!l) return -1
const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)
return bigint.intValue()
}
/**
* 获取 v 的位置
*/
function getStartOfV(str, start) {
const len = getLenOfL(str, start)
return start + (len + 1) * 2
}
module.exports = {
/**
* ASN.1 der 编码,针对 sm2 签名
*/
encodeDer(r, s) {
const derR = new DERInteger(r)
const derS = new DERInteger(s)
const derSeq = new DERSequence([derR, derS])
return derSeq.getEncodedHex()
},
/**
* 解析 ASN.1 der,针对 sm2 验签
*/
decodeDer(input) {
// 结构:
// input = | tSeq | lSeq | vSeq |
// vSeq = | tR | lR | vR | tS | lS | vS |
const start = getStartOfV(input, 0)
const vIndexR = getStartOfV(input, start)
const lR = getL(input, start)
const vR = input.substr(vIndexR, lR * 2)
const nextStart = vIndexR + vR.length
const vIndexS = getStartOfV(input, nextStart)
const lS = getL(input, nextStart)
const vS = input.substr(vIndexS, lS * 2)
const r = new BigInteger(vR, 16)
const s = new BigInteger(vS, 16)
return {r, s}
}
}
}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921841, function(require, module, exports) {
/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */
const {BigInteger, SecureRandom} = require('jsbn')
const {ECCurveFp} = require('./ec')
const rng = new SecureRandom()
const {curve, G, n} = generateEcparam()
/**
* 获取公共椭圆曲线
*/
function getGlobalCurve() {
return curve
}
/**
* 生成ecparam
*/
function generateEcparam() {
// 椭圆曲线
const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)
const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)
const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)
const curve = new ECCurveFp(p, a, b)
// 基点
const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'
const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'
const G = curve.decodePointHex('04' + gxHex + gyHex)
const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16)
return {curve, G, n}
}
/**
* 生成密钥对:publicKey = privateKey * G
*/
function generateKeyPairHex(a, b, c) {
const random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng)
const d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数
const privateKey = leftPad(d.toString(16), 64)
const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥
const Px = leftPad(P.getX().toBigInteger().toString(16), 64)
const Py = leftPad(P.getY().toBigInteger().toString(16), 64)
const publicKey = '04' + Px + Py
return {privateKey, publicKey}
}
/**
* 生成压缩公钥
*/
function compressPublicKeyHex(s) {
if (s.length !== 130) throw new Error('Invalid public key to compress')
const len = (s.length - 2) / 2
const xHex = s.substr(2, len)
const y = new BigInteger(s.substr(len + 2, len), 16)
let prefix = '03'
if (y.mod(new BigInteger('2')).equals(BigInteger.ZERO)) prefix = '02'
return prefix + xHex
}
/**
* utf8串转16进制串
*/
function utf8ToHex(input) {
input = unescape(encodeURIComponent(input))
const length = input.length
// 转换到字数组
const words = []
for (let i = 0; i < length; i++) {
words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)
}
// 转换到16进制
const hexChars = []
for (let i = 0; i < length; i++) {
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
hexChars.push((bite >>> 4).toString(16))
hexChars.push((bite & 0x0f).toString(16))
}
return hexChars.join('')
}
/**
* 补全16进制字符串
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 转成16进制串
*/
function arrayToHex(arr) {
return arr.map(item => {
item = item.toString(16)
return item.length === 1 ? '0' + item : item
}).join('')
}
/**
* 转成utf8串
*/
function arrayToUtf8(arr) {
const words = []
let j = 0
for (let i = 0; i < arr.length * 2; i += 2) {
words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)
j++
}
try {
const latin1Chars = []
for (let i = 0; i < arr.length; i++) {
const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff
latin1Chars.push(String.fromCharCode(bite))
}
return decodeURIComponent(escape(latin1Chars.join('')))
} catch (e) {
throw new Error('Malformed UTF-8 data')
}
}
/**
* 转成字节数组
*/
function hexToArray(hexStr) {
const words = []
let hexStrLength = hexStr.length
if (hexStrLength % 2 !== 0) {
hexStr = leftPad(hexStr, hexStrLength + 1)
}
hexStrLength = hexStr.length
for (let i = 0; i < hexStrLength; i += 2) {
words.push(parseInt(hexStr.substr(i, 2), 16))
}
return words
}
/**
* 验证公钥是否为椭圆曲线上的点
*/
function verifyPublicKey(publicKey) {
const point = curve.decodePointHex(publicKey)
if (!point) return false
const x = point.getX()
const y = point.getY()
// 验证 y^2 是否等于 x^3 + ax + b
return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b))
}
/**
* 验证公钥是否等价,等价返回true
*/
function comparePublicKeyHex(publicKey1, publicKey2) {
const point1 = curve.decodePointHex(publicKey1)
if (!point1) return false
const point2 = curve.decodePointHex(publicKey2)
if (!point2) return false
return point1.equals(point2)
}
module.exports = {
getGlobalCurve,
generateEcparam,
generateKeyPairHex,
compressPublicKeyHex,
utf8ToHex,
leftPad,
arrayToHex,
arrayToUtf8,
hexToArray,
verifyPublicKey,
comparePublicKeyHex,
}
}, function(modId) { var map = {"./ec":1743039921842}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921842, function(require, module, exports) {
/* eslint-disable no-case-declarations, max-len */
const {BigInteger} = require('jsbn')
/**
* thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/
*
* Basic Javascript Elliptic Curve implementation
* Ported loosely from BouncyCastle's Java EC code
* Only Fp curves implemented for now
*/
const TWO = new BigInteger('2')
const THREE = new BigInteger('3')
/**
* 椭圆曲线域元素
*/
class ECFieldElementFp {
constructor(q, x) {
this.x = x
this.q = q
// TODO if (x.compareTo(q) >= 0) error
}
/**
* 判断相等
*/
equals(other) {
if (other === this) return true
return (this.q.equals(other.q) && this.x.equals(other.x))
}
/**
* 返回具体数值
*/
toBigInteger() {
return this.x
}
/**
* 取反
*/
negate() {
return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))
}
/**
* 相加
*/
add(b) {
return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))
}
/**
* 相减
*/
subtract(b) {
return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))
}
/**
* 相乘
*/
multiply(b) {
return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))
}
/**
* 相除
*/
divide(b) {
return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q))
}
/**
* 平方
*/
square() {
return new ECFieldElementFp(this.q, this.x.square().mod(this.q))
}
}
class ECPointFp {
constructor(curve, x, y, z) {
this.curve = curve
this.x = x
this.y = y
// 标准射影坐标系:zinv == null 或 z * zinv == 1
this.z = z == null ? BigInteger.ONE : z
this.zinv = null
// TODO: compression flag
}
getX() {
if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q))
}
getY() {
if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)
return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q))
}
/**
* 判断相等
*/
equals(other) {
if (other === this) return true
if (this.isInfinity()) return other.isInfinity()
if (other.isInfinity()) return this.isInfinity()
// u = y2 * z1 - y1 * z2
const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q)
if (!u.equals(BigInteger.ZERO)) return false
// v = x2 * z1 - x1 * z2
const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q)
return v.equals(BigInteger.ZERO)
}
/**
* 是否是无穷远点
*/
isInfinity() {
if ((this.x === null) && (this.y === null)) return true
return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO)
}
/**
* 取反,x 轴对称点
*/
negate() {
return new ECPointFp(this.curve, this.x, this.y.negate(), this.z)
}
/**
* 相加
*
* 标准射影坐标系:
*
* λ1 = x1 * z2
* λ2 = x2 * z1
* λ3 = λ1 − λ2
* λ4 = y1 * z2
* λ5 = y2 * z1
* λ6 = λ4 − λ5
* λ7 = λ1 + λ2
* λ8 = z1 * z2
* λ9 = λ3^2
* λ10 = λ3 * λ9
* λ11 = λ8 * λ6^2 − λ7 * λ9
* x3 = λ3 * λ11
* y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10
* z3 = λ10 * λ8
*/
add(b) {
if (this.isInfinity()) return b
if (b.isInfinity()) return this
const x1 = this.x.toBigInteger()
const y1 = this.y.toBigInteger()
const z1 = this.z
const x2 = b.x.toBigInteger()
const y2 = b.y.toBigInteger()
const z2 = b.z
const q = this.curve.q
const w1 = x1.multiply(z2).mod(q)
const w2 = x2.multiply(z1).mod(q)
const w3 = w1.subtract(w2)
const w4 = y1.multiply(z2).mod(q)
const w5 = y2.multiply(z1).mod(q)
const w6 = w4.subtract(w5)
if (BigInteger.ZERO.equals(w3)) {
if (BigInteger.ZERO.equals(w6)) {
return this.twice() // this == b,计算自加
}
return this.curve.infinity // this == -b,则返回无穷远点
}
const w7 = w1.add(w2)
const w8 = z1.multiply(z2).mod(q)
const w9 = w3.square().mod(q)
const w10 = w3.multiply(w9).mod(q)
const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q)
const x3 = w3.multiply(w11).mod(q)
const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q)
const z3 = w10.multiply(w8).mod(q)
return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
}
/**
* 自加
*
* 标准射影坐标系:
*
* λ1 = 3 * x1^2 + a * z1^2
* λ2 = 2 * y1 * z1
* λ3 = y1^2
* λ4 = λ3 * x1 * z1
* λ5 = λ2^2
* λ6 = λ1^2 − 8 * λ4
* x3 = λ2 * λ6
* y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3
* z3 = λ2 * λ5
*/
twice() {
if (this.isInfinity()) return this
if (!this.y.toBigInteger().signum()) return this.curve.infinity
const x1 = this.x.toBigInteger()
const y1 = this.y.toBigInteger()
const z1 = this.z
const q = this.curve.q
const a = this.curve.a.toBigInteger()
const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q)
const w2 = y1.shiftLeft(1).multiply(z1).mod(q)
const w3 = y1.square().mod(q)
const w4 = w3.multiply(x1).multiply(z1).mod(q)
const w5 = w2.square().mod(q)
const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q)
const x3 = w2.multiply(w6).mod(q)
const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q)
const z3 = w2.multiply(w5).mod(q)
return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)
}
/**
* 倍点计算
*/
multiply(k) {
if (this.isInfinity()) return this
if (!k.signum()) return this.curve.infinity
// 使用加减法
const k3 = k.multiply(THREE)
const neg = this.negate()
let Q = this
for (let i = k3.bitLength() - 2; i > 0; i--) {
Q = Q.twice()
const k3Bit = k3.testBit(i)
const kBit = k.testBit(i)
if (k3Bit !== kBit) {
Q = Q.add(k3Bit ? this : neg)
}
}
return Q
}
}
/**
* 椭圆曲线 y^2 = x^3 + ax + b
*/
class ECCurveFp {
constructor(q, a, b) {
this.q = q
this.a = this.fromBigInteger(a)
this.b = this.fromBigInteger(b)
this.infinity = new ECPointFp(this, null, null) // 无穷远点
}
/**
* 判断两个椭圆曲线是否相等
*/
equals(other) {
if (other === this) return true
return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))
}
/**
* 生成椭圆曲线域元素
*/
fromBigInteger(x) {
return new ECFieldElementFp(this.q, x)
}
/**
* 解析 16 进制串为椭圆曲线点
*/
decodePointHex(s) {
switch (parseInt(s.substr(0, 2), 16)) {
// 第一个字节
case 0:
return this.infinity
case 2:
case 3:
// 压缩
const x = this.fromBigInteger(new BigInteger(s.substr(2), 16))
// 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3
// 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp
let y = this.fromBigInteger(x.multiply(x.square()).add(
x.multiply(this.a)
).add(this.b).toBigInteger()
.modPow(
this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q
))
// 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反
if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {
y = y.negate()
}
return new ECPointFp(this, x, y)
case 4:
case 6:
case 7:
const len = (s.length - 2) / 2
const xHex = s.substr(2, len)
const yHex = s.substr(len + 2, len)
return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)))
default:
// 不支持
return null
}
}
}
module.exports = {
ECPointFp,
ECCurveFp,
}
}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921843, function(require, module, exports) {
// 消息扩展
const W = new Uint32Array(68)
const M = new Uint32Array(64) // W'
/**
* 循环左移
*/
function rotl(x, n) {
const s = n & 31
return (x << s) | (x >>> (32 - s))
}
/**
* 二进制异或运算
*/
function xor(x, y) {
const result = []
for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff
return result
}
/**
* 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)
*/
function P0(X) {
return (X ^ rotl(X, 9)) ^ rotl(X, 17)
}
/**
* 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)
*/
function P1(X) {
return (X ^ rotl(X, 15)) ^ rotl(X, 23)
}
/**
* sm3 本体
*/
function sm3(array) {
let len = array.length * 8
// k 是满足 len + 1 + k = 448mod512 的最小的非负整数
let k = len % 512
// 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数
k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1
// 填充
const kArr = new Array((k - 7) / 8)
const lenArr = new Array(8)
for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0
for (let i = 0, len = lenArr.length; i < len; i++) lenArr[i] = 0
len = len.toString(2)
for (let i = 7; i >= 0; i--) {
if (len.length > 8) {
const start = len.length - 8
lenArr[i] = parseInt(len.substr(start), 2)
len = len.substr(0, start)
} else if (len.length > 0) {
lenArr[i] = parseInt(len, 2)
len = ''
}
}
const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr])
const dataView = new DataView(m.buffer, 0)
// 迭代压缩
const n = m.length / 64
const V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])
for (let i = 0; i < n; i++) {
W.fill(0)
M.fill(0)
// 将消息分组B划分为 16 个字 W0, W1,……,W15
const start = 16 * i
for (let j = 0; j < 16; j++) {
W[j] = dataView.getUint32((start + j) * 4, false)
}
// W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]
for (let j = 16; j < 68; j++) {
W[j] = (P1((W[j - 16] ^ W[j - 9]) ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7)) ^ W[j - 6]
}
// W′0 ~ W′63:W′[j] = W[j] xor W[j+4]
for (let j = 0; j < 64; j++) {
M[j] = W[j] ^ W[j + 4]
}
// 压缩
const T1 = 0x79cc4519
const T2 = 0x7a879d8a
// 字寄存器
let A = V[0]
let B = V[1]
let C = V[2]
let D = V[3]
let E = V[4]
let F = V[5]
let G = V[6]
let H = V[7]
// 中间变量
let SS1
let SS2
let TT1
let TT2
let T
for (let j = 0; j < 64; j++) {
T = j >= 0 && j <= 15 ? T1 : T2
SS1 = rotl(rotl(A, 12) + E + rotl(T, j), 7)
SS2 = SS1 ^ rotl(A, 12)
TT1 = (j >= 0 && j <= 15 ? ((A ^ B) ^ C) : (((A & B) | (A & C)) | (B & C))) + D + SS2 + M[j]
TT2 = (j >= 0 && j <= 15 ? ((E ^ F) ^ G) : ((E & F) | ((~E) & G))) + H + SS1 + W[j]
D = C
C = rotl(B, 9)
B = A
A = TT1
H = G
G = rotl(F, 19)
F = E
E = P0(TT2)
}
V[0] ^= A
V[1] ^= B
V[2] ^= C
V[3] ^= D
V[4] ^= E
V[5] ^= F
V[6] ^= G
V[7] ^= H
}
// 转回 uint8
const result = []
for (let i = 0, len = V.length; i < len; i++) {
const word = V[i]
result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff)
}
return result
}
/**
* hmac 实现
*/
const blockLen = 64
const iPad = new Uint8Array(blockLen)
const oPad = new Uint8Array(blockLen)
for (let i = 0; i < blockLen; i++) {
iPad[i] = 0x36
oPad[i] = 0x5c
}
function hmac(input, key) {
// 密钥填充
if (key.length > blockLen) key = sm3(key)
while (key.length < blockLen) key.push(0)
const iPadKey = xor(key, iPad)
const oPadKey = xor(key, oPad)
const hash = sm3([...iPadKey, ...input])
return sm3([...oPadKey, ...hash])
}
module.exports = {
sm3,
hmac,
}
}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921844, function(require, module, exports) {
const {sm3, hmac} = require('../sm2/sm3')
/**
* 补全16进制字符串
*/
function leftPad(input, num) {
if (input.length >= num) return input
return (new Array(num - input.length + 1)).join('0') + input
}
/**
* 字节数组转 16 进制串
*/
function ArrayToHex(arr) {
return arr.map(item => {
item = item.toString(16)
return item.length === 1 ? '0' + item : item
}).join('')
}
/**
* 转成字节数组
*/
function hexToArray(hexStr) {
const words = []
let hexStrLength = hexStr.length
if (hexStrLength % 2 !== 0) {
hexStr = leftPad(hexStr, hexStrLength + 1)
}
hexStrLength = hexStr.length
for (let i = 0; i < hexStrLength; i += 2) {
words.push(parseInt(hexStr.substr(i, 2), 16))
}
return words
}
/**
* utf8 串转字节数组
*/
function utf8ToArray(str) {
const arr = []
for (let i = 0, len = str.length; i < len; i++) {
const point = str.codePointAt(i)
if (point <= 0x007f) {
// 单字节,标量值:00000000 00000000 0zzzzzzz
arr.push(point)
} else if (point <= 0x07ff) {
// 双字节,标量值:00000000 00000yyy yyzzzzzz
arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
} else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
// 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
} else if (point >= 0x010000 && point <= 0x10FFFF) {
// 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
i++
arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
} else {
// 五、六字节,暂时不支持
arr.push(point)
throw new Error('input is not supported')
}
}
return arr
}
module.exports = function (input, options) {
input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input)
if (options) {
const mode = options.mode || 'hmac'
if (mode !== 'hmac') throw new Error('invalid mode')
let key = options.key
if (!key) throw new Error('invalid key')
key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key)
return ArrayToHex(hmac(input, key))
}
return ArrayToHex(sm3(input))
}
}, function(modId) { var map = {"../sm2/sm3":1743039921843}; return __REQUIRE__(map[modId], modId); })
__DEFINE__(1743039921845, function(require, module, exports) {
/* eslint-disable no-bitwise, no-mixed-operators, complexity */
const DECRYPT = 0
const ROUND = 32
const BLOCK = 16
const Sbox = [
0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,
0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,
0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,
0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,
0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,
0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,
0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,
0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,
0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,
0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,
0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,
0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,
0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,
0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,
0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,
0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48
]
const CK = [
0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,
0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,
0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,
0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,
0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,
0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,
0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,
0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279
]
/**
* 16 进制串转字节数组
*/
function hexToArray(str) {
const arr = []
for (let i = 0, len = str.length; i < len; i += 2) {
arr.push(parseInt(str.substr(i, 2), 16))
}
return arr
}
/**
* 字节数组转 16 进制串
*/
function ArrayToHex(arr) {
return arr.map(item => {
item = item.toString(16)
return item.length === 1 ? '0' + item : item
}).join('')
}
/**
* utf8 串转字节数组
*/
function utf8ToArray(str) {
const arr = []
for (let i = 0, len = str.length; i < len; i++) {
const point = str.codePointAt(i)
if (point <= 0x007f) {
// 单字节,标量值:00000000 00000000 0zzzzzzz
arr.push(point)
} else if (point <= 0x07ff) {
// 双字节,标量值:00000000 00000yyy yyzzzzzz
arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)
arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
} else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {
// 三字节:标量值:00000000 xxxxyyyy yyzzzzzz
arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)
arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)
arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)
} else if (point >= 0x010000 && point <= 0x10FFFF) {
// 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz
i++
arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)
arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)
arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)
arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)
} else {
// 五、六字节,暂时不支持
arr.push(point)
throw new Error('input is not supported')
}
}
return arr
}
/**
* 字节数组转 utf8 串
*/
function arrayToUtf8(arr) {
const str = []
for (let i = 0, len = arr.length; i < len; i++) {
if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {
// 四字节
str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)))
i += 3
} else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {
// 三字节
str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)))
i += 2
} else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {
// 双字节
str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)))
i++
} else {
// 单字节
str.push(String.fromCodePoint(arr[i]))
}
}
return str.join('')
}
/**
* 32 比特循环左移
*/
function rotl(x, n) {
const s = n & 31
return (x << s) | (x >>> (32 - s))
}
/**
* 非线性变换
*/
function byteSub(a) {
return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 |
(Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 |
(Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 |
(Sbox[a & 0xFF] & 0xFF)
}
/**
* 线性变换,加密/解密用
*/
function l1(b) {
return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24)
}
/**
* 线性变换,生成轮密钥用
*/
function l2(b) {
return b ^ rotl(b, 13) ^ rotl(b, 23)
}
/**
* 以一组 128 比特进行加密/解密操作
*/
function sms4Crypt(input, output, roundKey) {
const x = new Array(4)
// 字节数组转成字数组(此处 1 字 = 32 比特)
const tmp = new Array(4)
for (let i = 0; i < 4; i++) {
tmp[0] = input[4 * i] & 0xff
tmp[1] = input[4 * i + 1] & 0xff
tmp[2] = input[4 * i + 2] & 0xff
tmp[3] = input[4 * i + 3] & 0xff
x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
}
// x[i + 4] = x[i] ^ l1(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ roundKey[i]))
for (let r = 0, mid; r < 32; r += 4) {
mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0]
x[0] ^= l1(byteSub(mid)) // x[4]
mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1]
x[1] ^= l1(byteSub(mid)) // x[5]
mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2]
x[2] ^= l1(byteSub(mid)) // x[6]
mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3]
x[3] ^= l1(byteSub(mid)) // x[7]
}
// 反序变换
for (let j = 0; j < 16; j += 4) {
output[j] = x[3 - j / 4] >>> 24 & 0xff
output[j + 1] = x[3 - j / 4] >>> 16 & 0xff
output[j + 2] = x[3 - j / 4] >>> 8 & 0xff
output[j + 3] = x[3 - j / 4] & 0xff
}
}
/**
* 密钥扩展算法
*/
function sms4KeyExt(key, roundKey, cryptFlag) {
const x = new Array(4)
// 字节数组转成字数组(此处 1 字 = 32 比特)
const tmp = new Array(4)
for (let i = 0; i < 4; i++) {
tmp[0] = key[0 + 4 * i] & 0xff
tmp[1] = key[1 + 4 * i] & 0xff
tmp[2] = key[2 + 4 * i] & 0xff
tmp[3] = key[3 + 4 * i] & 0xff
x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]
}
// 与系统参数做异或
x[0] ^= 0xa3b1bac6
x[1] ^= 0x56aa3350
x[2] ^= 0x677d9197
x[3] ^= 0xb27022dc
// roundKey[i] = x[i + 4] = x[i] ^ l2(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ CK[i]))
for (let r = 0, mid; r < 32; r += 4) {
mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]
roundKey[r + 0] = x[0] ^= l2(byteSub(mid)) // x[4]
mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]
roundKey[r + 1] = x[1] ^= l2(byteSub(mid)) // x[5]
mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]
roundKey[r + 2] = x[2] ^= l2(byteSub(mid)) // x[6]
mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]
roundKey[r + 3] = x[3] ^= l2(byteSub(mid)) // x[7]
}
// 解密时使用反序的轮密钥
if (cryptFlag === DECRYPT) {
for (let r = 0, mid; r < 16; r++) {
mid = roundKey[r]
roundKey[r] = roundKey[31 - r]
roundKey[31 - r] = mid
}
}
}
function sm4(inArray, key, cryptFlag, {
padding = 'pkcs#7', mode, iv = [], output = 'string'
} = {}) {
if (mode === 'cbc') {
// CBC 模式,默认走 ECB 模式
if (typeof iv === 'string') iv = hexToArray(iv)
if (iv.length !== (128 / 8)) {
// iv 不是 128 比特
throw new Error('iv is invalid')
}
}
// 检查 key
if (typeof key === 'string') key = hexToArray(key)
if (key.length !== (128 / 8)) {
// key 不是 128 比特
throw new Error('key is invalid')
}
// 检查输入
if (typeof inArray === 'string') {
if (cryptFlag !== DECRYPT) {
// 加密,输入为 utf8 串
inArray = utf8ToArray(inArray)
} else {
// 解密,输入为 16 进制串
inArray = hexToArray(inArray)
}
} else {
inArray = [...inArray]
}
// 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {
const paddingCount = BLOCK - inArray.length % BLOCK
for (let i = 0; i < paddingCount; i++) inArray.push(paddingCount)
}
// 生成轮密钥
const roundKey = new Array(ROUND)
sms4KeyExt(key, roundKey, cryptFlag)
const outArray = []
let lastVector = iv
let restLen = inArray.length
let point = 0
while (restLen >= BLOCK) {
const input = inArray.slice(point, point + 16)
const output = new Array(16)
if (mode === 'cbc') {
for (let i = 0; i < BLOCK; i++) {
if (cryptFlag !== DECRYPT) {
// 加密过程在组加密前进行异或
input[i] ^= lastVector[i]
}
}
}
sms4Crypt(input, output, roundKey)
for (let i = 0; i < BLOCK; i++) {
if (mode === 'cbc') {
if (cryptFlag === DECRYPT) {
// 解密过程在组解密后进行异或
output[i] ^= lastVector[i]
}
}
outArray[point + i] = output[i]
}
if (mode === 'cbc') {
if (cryptFlag !== DECRYPT) {
// 使用上一次输出作为加密向量
lastVector = output
} else {
// 使用上一次输入作为解密向量
lastVector = input
}
}
restLen -= BLOCK
point += BLOCK
}
// 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7
if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {
const len = outArray.length
const paddingCount = outArray[len - 1]
for (let i = 1; i <= paddingCount; i++) {
if (outArray[len - i] !== paddingCount) throw new Error('padding is invalid')
}
outArray.splice(len - paddingCount, paddingCount)
}
// 调整输出
if (output !== 'array') {
if (cryptFlag !== DECRYPT) {
// 加密,输出转 16 进制串
return ArrayToHex(outArray)
} else {
// 解密,输出转 utf8 串
return arrayToUtf8(outArray)
}
} else {
return outArray
}
}
module.exports = {
encrypt(inArray, key, options) {
return sm4(inArray, key, 1, options)
},
decrypt(inArray, key, options) {
return sm4(inArray, key, 0, options)
}
}
}, function(modId) { var map = {}; return __REQUIRE__(map[modId], modId); })
return __REQUIRE__(1743039921838);
})()
//miniprogram-npm-outsideDeps=["jsbn"]
//# sourceMappingURL=index.js.map
\ No newline at end of file
{"version":3,"sources":["index.js","sm2/index.js","sm2/asn1.js","sm2/utils.js","sm2/ec.js","sm2/sm3.js","sm3/index.js","sm4/index.js"],"names":[],"mappings":";;;;;;;AAAA;AACA;AACA;AACA,ACHA;ADIA,ACHA;ADIA,ACHA;ACFA,ADGA;ACFA,ADGA;ACFA,ADGA;ACFA,ADGA,AENA;ADIA,ADGA,AENA;ADIA,ADGA,AENA;ADIA,AENA,AHSA,AENA;ADIA,AENA,AHSA,AENA;ADIA,AENA,AHSA,AENA;ADIA,AENA,AHSA,AIZA,AFMA;ADIA,AENA,AHSA,AIZA,AFMA;ADIA,AENA,AHSA,AIZA,AFMA;ADIA,AENA,AHSA,AIZA,AFMA,AGTA;AJaA,AENA,AHSA,AIZA,AFMA,AGTA;AJaA,AENA,AHSA,AIZA,AFMA,AGTA;AJaA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AGTA,ACHA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;ALgBA,AENA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AIZA,AFMA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AENA,AIZA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AHSA,AMlBA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AHUA,AGTA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"index.js","sourcesContent":["module.exports = {\n sm2: require('./sm2/index'),\n sm3: require('./sm3/index'),\n sm4: require('./sm4/index'),\n}\n","/* eslint-disable no-use-before-define */\nconst {BigInteger} = require('jsbn')\nconst {encodeDer, decodeDer} = require('./asn1')\nconst _ = require('./utils')\nconst sm3 = require('./sm3').sm3\n\nconst {G, curve, n} = _.generateEcparam()\nconst C1C2C3 = 0\n\n/**\n * 加密\n */\nfunction doEncrypt(msg, publicKey, cipherMode = 1) {\n msg = typeof msg === 'string' ? _.hexToArray(_.utf8ToHex(msg)) : Array.prototype.slice.call(msg)\n publicKey = _.getGlobalCurve().decodePointHex(publicKey) // 先将公钥转成点\n\n const keypair = _.generateKeyPairHex()\n const k = new BigInteger(keypair.privateKey, 16) // 随机数 k\n\n // c1 = k * G\n let c1 = keypair.publicKey\n if (c1.length > 128) c1 = c1.substr(c1.length - 128)\n\n // (x2, y2) = k * publicKey\n const p = publicKey.multiply(k)\n const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))\n const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))\n\n // c3 = hash(x2 || msg || y2)\n const c3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))\n\n let ct = 1\n let offset = 0\n let t = [] // 256 位\n const z = [].concat(x2, y2)\n const nextT = () => {\n // (1) Hai = hash(z || ct)\n // (2) ct++\n t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])\n ct++\n offset = 0\n }\n nextT() // 先生成 Ha1\n\n for (let i = 0, len = msg.length; i < len; i++) {\n // t = Ha1 || Ha2 || Ha3 || Ha4\n if (offset === t.length) nextT()\n\n // c2 = msg ^ t\n msg[i] ^= t[offset++] & 0xff\n }\n const c2 = _.arrayToHex(msg)\n\n return cipherMode === C1C2C3 ? c1 + c2 + c3 : c1 + c3 + c2\n}\n\n/**\n * 解密\n */\nfunction doDecrypt(encryptData, privateKey, cipherMode = 1, {\n output = 'string',\n} = {}) {\n privateKey = new BigInteger(privateKey, 16)\n\n let c3 = encryptData.substr(128, 64)\n let c2 = encryptData.substr(128 + 64)\n\n if (cipherMode === C1C2C3) {\n c3 = encryptData.substr(encryptData.length - 64)\n c2 = encryptData.substr(128, encryptData.length - 128 - 64)\n }\n\n const msg = _.hexToArray(c2)\n const c1 = _.getGlobalCurve().decodePointHex('04' + encryptData.substr(0, 128))\n\n const p = c1.multiply(privateKey)\n const x2 = _.hexToArray(_.leftPad(p.getX().toBigInteger().toRadix(16), 64))\n const y2 = _.hexToArray(_.leftPad(p.getY().toBigInteger().toRadix(16), 64))\n\n let ct = 1\n let offset = 0\n let t = [] // 256 位\n const z = [].concat(x2, y2)\n const nextT = () => {\n // (1) Hai = hash(z || ct)\n // (2) ct++\n t = sm3([...z, ct >> 24 & 0x00ff, ct >> 16 & 0x00ff, ct >> 8 & 0x00ff, ct & 0x00ff])\n ct++\n offset = 0\n }\n nextT() // 先生成 Ha1\n\n for (let i = 0, len = msg.length; i < len; i++) {\n // t = Ha1 || Ha2 || Ha3 || Ha4\n if (offset === t.length) nextT()\n\n // c2 = msg ^ t\n msg[i] ^= t[offset++] & 0xff\n }\n\n // c3 = hash(x2 || msg || y2)\n const checkC3 = _.arrayToHex(sm3([].concat(x2, msg, y2)))\n\n if (checkC3 === c3.toLowerCase()) {\n return output === 'array' ? msg : _.arrayToUtf8(msg)\n } else {\n return output === 'array' ? [] : ''\n }\n}\n\n/**\n * 签名\n */\nfunction doSignature(msg, privateKey, {\n pointPool, der, hash, publicKey, userId\n} = {}) {\n let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)\n\n if (hash) {\n // sm3杂凑\n publicKey = publicKey || getPublicKeyFromPrivateKey(privateKey)\n hashHex = getHash(hashHex, publicKey, userId)\n }\n\n const dA = new BigInteger(privateKey, 16)\n const e = new BigInteger(hashHex, 16)\n\n // k\n let k = null\n let r = null\n let s = null\n\n do {\n do {\n let point\n if (pointPool && pointPool.length) {\n point = pointPool.pop()\n } else {\n point = getPoint()\n }\n k = point.k\n\n // r = (e + x1) mod n\n r = e.add(point.x1).mod(n)\n } while (r.equals(BigInteger.ZERO) || r.add(k).equals(n))\n\n // s = ((1 + dA)^-1 * (k - r * dA)) mod n\n s = dA.add(BigInteger.ONE).modInverse(n).multiply(k.subtract(r.multiply(dA))).mod(n)\n } while (s.equals(BigInteger.ZERO))\n\n if (der) return encodeDer(r, s) // asn.1 der 编码\n\n return _.leftPad(r.toString(16), 64) + _.leftPad(s.toString(16), 64)\n}\n\n/**\n * 验签\n */\nfunction doVerifySignature(msg, signHex, publicKey, {der, hash, userId} = {}) {\n let hashHex = typeof msg === 'string' ? _.utf8ToHex(msg) : _.arrayToHex(msg)\n\n if (hash) {\n // sm3杂凑\n hashHex = getHash(hashHex, publicKey, userId)\n }\n\n let r; let\n s\n if (der) {\n const decodeDerObj = decodeDer(signHex) // asn.1 der 解码\n r = decodeDerObj.r\n s = decodeDerObj.s\n } else {\n r = new BigInteger(signHex.substring(0, 64), 16)\n s = new BigInteger(signHex.substring(64), 16)\n }\n\n const PA = curve.decodePointHex(publicKey)\n const e = new BigInteger(hashHex, 16)\n\n // t = (r + s) mod n\n const t = r.add(s).mod(n)\n\n if (t.equals(BigInteger.ZERO)) return false\n\n // x1y1 = s * G + t * PA\n const x1y1 = G.multiply(s).add(PA.multiply(t))\n\n // R = (e + x1) mod n\n const R = e.add(x1y1.getX().toBigInteger()).mod(n)\n\n return r.equals(R)\n}\n\n/**\n * sm3杂凑算法\n */\nfunction getHash(hashHex, publicKey, userId = '1234567812345678') {\n // z = hash(entl || userId || a || b || gx || gy || px || py)\n userId = _.utf8ToHex(userId)\n const a = _.leftPad(G.curve.a.toBigInteger().toRadix(16), 64)\n const b = _.leftPad(G.curve.b.toBigInteger().toRadix(16), 64)\n const gx = _.leftPad(G.getX().toBigInteger().toRadix(16), 64)\n const gy = _.leftPad(G.getY().toBigInteger().toRadix(16), 64)\n let px\n let py\n if (publicKey.length === 128) {\n px = publicKey.substr(0, 64)\n py = publicKey.substr(64, 64)\n } else {\n const point = G.curve.decodePointHex(publicKey)\n px = _.leftPad(point.getX().toBigInteger().toRadix(16), 64)\n py = _.leftPad(point.getY().toBigInteger().toRadix(16), 64)\n }\n const data = _.hexToArray(userId + a + b + gx + gy + px + py)\n\n const entl = userId.length * 4\n data.unshift(entl & 0x00ff)\n data.unshift(entl >> 8 & 0x00ff)\n\n const z = sm3(data)\n\n // e = hash(z || msg)\n return _.arrayToHex(sm3(z.concat(_.hexToArray(hashHex))))\n}\n\n/**\n * 计算公钥\n */\nfunction getPublicKeyFromPrivateKey(privateKey) {\n const PA = G.multiply(new BigInteger(privateKey, 16))\n const x = _.leftPad(PA.getX().toBigInteger().toString(16), 64)\n const y = _.leftPad(PA.getY().toBigInteger().toString(16), 64)\n return '04' + x + y\n}\n\n/**\n * 获取椭圆曲线点\n */\nfunction getPoint() {\n const keypair = _.generateKeyPairHex()\n const PA = curve.decodePointHex(keypair.publicKey)\n\n keypair.k = new BigInteger(keypair.privateKey, 16)\n keypair.x1 = PA.getX().toBigInteger()\n\n return keypair\n}\n\nmodule.exports = {\n generateKeyPairHex: _.generateKeyPairHex,\n compressPublicKeyHex: _.compressPublicKeyHex,\n comparePublicKeyHex: _.comparePublicKeyHex,\n doEncrypt,\n doDecrypt,\n doSignature,\n doVerifySignature,\n getPublicKeyFromPrivateKey,\n getPoint,\n verifyPublicKey: _.verifyPublicKey,\n}\n","/* eslint-disable class-methods-use-this */\r\nconst {BigInteger} = require('jsbn')\r\n\r\nfunction bigintToValue(bigint) {\r\n let h = bigint.toString(16)\r\n if (h[0] !== '-') {\r\n // 正数\r\n if (h.length % 2 === 1) h = '0' + h // 补齐到整字节\r\n else if (!h.match(/^[0-7]/)) h = '00' + h // 非0开头,则补一个全0字节\r\n } else {\r\n // 负数\r\n h = h.substr(1)\r\n\r\n let len = h.length\r\n if (len % 2 === 1) len += 1 // 补齐到整字节\r\n else if (!h.match(/^[0-7]/)) len += 2 // 非0开头,则补一个全0字节\r\n\r\n let mask = ''\r\n for (let i = 0; i < len; i++) mask += 'f'\r\n mask = new BigInteger(mask, 16)\r\n\r\n // 对绝对值取反,加1\r\n h = mask.xor(bigint).add(BigInteger.ONE)\r\n h = h.toString(16).replace(/^-/, '')\r\n }\r\n return h\r\n}\r\n\r\nclass ASN1Object {\r\n constructor() {\r\n this.tlv = null\r\n this.t = '00'\r\n this.l = '00'\r\n this.v = ''\r\n }\r\n\r\n /**\r\n * 获取 der 编码比特流16进制串\r\n */\r\n getEncodedHex() {\r\n if (!this.tlv) {\r\n this.v = this.getValue()\r\n this.l = this.getLength()\r\n this.tlv = this.t + this.l + this.v\r\n }\r\n return this.tlv\r\n }\r\n\r\n getLength() {\r\n const n = this.v.length / 2 // 字节数\r\n let nHex = n.toString(16)\r\n if (nHex.length % 2 === 1) nHex = '0' + nHex // 补齐到整字节\r\n\r\n if (n < 128) {\r\n // 短格式,以 0 开头\r\n return nHex\r\n } else {\r\n // 长格式,以 1 开头\r\n const head = 128 + nHex.length / 2 // 1(1位) + 真正的长度占用字节数(7位) + 真正的长度\r\n return head.toString(16) + nHex\r\n }\r\n }\r\n\r\n getValue() {\r\n return ''\r\n }\r\n}\r\n\r\nclass DERInteger extends ASN1Object {\r\n constructor(bigint) {\r\n super()\r\n\r\n this.t = '02' // 整型标签说明\r\n if (bigint) this.v = bigintToValue(bigint)\r\n }\r\n\r\n getValue() {\r\n return this.v\r\n }\r\n}\r\n\r\nclass DERSequence extends ASN1Object {\r\n constructor(asn1Array) {\r\n super()\r\n\r\n this.t = '30' // 序列标签说明\r\n this.asn1Array = asn1Array\r\n }\r\n\r\n getValue() {\r\n this.v = this.asn1Array.map(asn1Object => asn1Object.getEncodedHex()).join('')\r\n return this.v\r\n }\r\n}\r\n\r\n/**\r\n * 获取 l 占用字节数\r\n */\r\nfunction getLenOfL(str, start) {\r\n if (+str[start + 2] < 8) return 1 // l 以0开头,则表示短格式,只占一个字节\r\n return +str.substr(start + 2, 2) & 0x7f + 1 // 长格式,取第一个字节后7位作为长度真正占用字节数,再加上本身\r\n}\r\n\r\n/**\r\n * 获取 l\r\n */\r\nfunction getL(str, start) {\r\n // 获取 l\r\n const len = getLenOfL(str, start)\r\n const l = str.substr(start + 2, len * 2)\r\n\r\n if (!l) return -1\r\n const bigint = +l[0] < 8 ? new BigInteger(l, 16) : new BigInteger(l.substr(2), 16)\r\n\r\n return bigint.intValue()\r\n}\r\n\r\n/**\r\n * 获取 v 的位置\r\n */\r\nfunction getStartOfV(str, start) {\r\n const len = getLenOfL(str, start)\r\n return start + (len + 1) * 2\r\n}\r\n\r\nmodule.exports = {\r\n /**\r\n * ASN.1 der 编码,针对 sm2 签名\r\n */\r\n encodeDer(r, s) {\r\n const derR = new DERInteger(r)\r\n const derS = new DERInteger(s)\r\n const derSeq = new DERSequence([derR, derS])\r\n\r\n return derSeq.getEncodedHex()\r\n },\r\n\r\n /**\r\n * 解析 ASN.1 der,针对 sm2 验签\r\n */\r\n decodeDer(input) {\r\n // 结构:\r\n // input = | tSeq | lSeq | vSeq |\r\n // vSeq = | tR | lR | vR | tS | lS | vS |\r\n const start = getStartOfV(input, 0)\r\n\r\n const vIndexR = getStartOfV(input, start)\r\n const lR = getL(input, start)\r\n const vR = input.substr(vIndexR, lR * 2)\r\n\r\n const nextStart = vIndexR + vR.length\r\n const vIndexS = getStartOfV(input, nextStart)\r\n const lS = getL(input, nextStart)\r\n const vS = input.substr(vIndexS, lS * 2)\r\n\r\n const r = new BigInteger(vR, 16)\r\n const s = new BigInteger(vS, 16)\r\n\r\n return {r, s}\r\n }\r\n}\r\n","/* eslint-disable no-bitwise, no-mixed-operators, no-use-before-define, max-len */\nconst {BigInteger, SecureRandom} = require('jsbn')\nconst {ECCurveFp} = require('./ec')\n\nconst rng = new SecureRandom()\nconst {curve, G, n} = generateEcparam()\n\n/**\n * 获取公共椭圆曲线\n */\nfunction getGlobalCurve() {\n return curve\n}\n\n/**\n * 生成ecparam\n */\nfunction generateEcparam() {\n // 椭圆曲线\n const p = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFF', 16)\n const a = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF00000000FFFFFFFFFFFFFFFC', 16)\n const b = new BigInteger('28E9FA9E9D9F5E344D5A9E4BCF6509A7F39789F515AB8F92DDBCBD414D940E93', 16)\n const curve = new ECCurveFp(p, a, b)\n\n // 基点\n const gxHex = '32C4AE2C1F1981195F9904466A39C9948FE30BBFF2660BE1715A4589334C74C7'\n const gyHex = 'BC3736A2F4F6779C59BDCEE36B692153D0A9877CC62A474002DF32E52139F0A0'\n const G = curve.decodePointHex('04' + gxHex + gyHex)\n\n const n = new BigInteger('FFFFFFFEFFFFFFFFFFFFFFFFFFFFFFFF7203DF6B21C6052B53BBF40939D54123', 16)\n\n return {curve, G, n}\n}\n\n/**\n * 生成密钥对:publicKey = privateKey * G\n */\nfunction generateKeyPairHex(a, b, c) {\n const random = a ? new BigInteger(a, b, c) : new BigInteger(n.bitLength(), rng)\n const d = random.mod(n.subtract(BigInteger.ONE)).add(BigInteger.ONE) // 随机数\n const privateKey = leftPad(d.toString(16), 64)\n\n const P = G.multiply(d) // P = dG,p 为公钥,d 为私钥\n const Px = leftPad(P.getX().toBigInteger().toString(16), 64)\n const Py = leftPad(P.getY().toBigInteger().toString(16), 64)\n const publicKey = '04' + Px + Py\n\n return {privateKey, publicKey}\n}\n\n/**\n * 生成压缩公钥\n */\nfunction compressPublicKeyHex(s) {\n if (s.length !== 130) throw new Error('Invalid public key to compress')\n\n const len = (s.length - 2) / 2\n const xHex = s.substr(2, len)\n const y = new BigInteger(s.substr(len + 2, len), 16)\n\n let prefix = '03'\n if (y.mod(new BigInteger('2')).equals(BigInteger.ZERO)) prefix = '02'\n\n return prefix + xHex\n}\n\n/**\n * utf8串转16进制串\n */\nfunction utf8ToHex(input) {\n input = unescape(encodeURIComponent(input))\n\n const length = input.length\n\n // 转换到字数组\n const words = []\n for (let i = 0; i < length; i++) {\n words[i >>> 2] |= (input.charCodeAt(i) & 0xff) << (24 - (i % 4) * 8)\n }\n\n // 转换到16进制\n const hexChars = []\n for (let i = 0; i < length; i++) {\n const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff\n hexChars.push((bite >>> 4).toString(16))\n hexChars.push((bite & 0x0f).toString(16))\n }\n\n return hexChars.join('')\n}\n\n/**\n * 补全16进制字符串\n */\nfunction leftPad(input, num) {\n if (input.length >= num) return input\n\n return (new Array(num - input.length + 1)).join('0') + input\n}\n\n/**\n * 转成16进制串\n */\nfunction arrayToHex(arr) {\n return arr.map(item => {\n item = item.toString(16)\n return item.length === 1 ? '0' + item : item\n }).join('')\n}\n\n/**\n * 转成utf8串\n */\nfunction arrayToUtf8(arr) {\n const words = []\n let j = 0\n for (let i = 0; i < arr.length * 2; i += 2) {\n words[i >>> 3] |= parseInt(arr[j], 10) << (24 - (i % 8) * 4)\n j++\n }\n\n try {\n const latin1Chars = []\n\n for (let i = 0; i < arr.length; i++) {\n const bite = (words[i >>> 2] >>> (24 - (i % 4) * 8)) & 0xff\n latin1Chars.push(String.fromCharCode(bite))\n }\n\n return decodeURIComponent(escape(latin1Chars.join('')))\n } catch (e) {\n throw new Error('Malformed UTF-8 data')\n }\n}\n\n/**\n * 转成字节数组\n */\nfunction hexToArray(hexStr) {\n const words = []\n let hexStrLength = hexStr.length\n\n if (hexStrLength % 2 !== 0) {\n hexStr = leftPad(hexStr, hexStrLength + 1)\n }\n\n hexStrLength = hexStr.length\n\n for (let i = 0; i < hexStrLength; i += 2) {\n words.push(parseInt(hexStr.substr(i, 2), 16))\n }\n return words\n}\n\n/**\n * 验证公钥是否为椭圆曲线上的点\n */\nfunction verifyPublicKey(publicKey) {\n const point = curve.decodePointHex(publicKey)\n if (!point) return false\n\n const x = point.getX()\n const y = point.getY()\n\n // 验证 y^2 是否等于 x^3 + ax + b\n return y.square().equals(x.multiply(x.square()).add(x.multiply(curve.a)).add(curve.b))\n}\n\n/**\n * 验证公钥是否等价,等价返回true\n */\nfunction comparePublicKeyHex(publicKey1, publicKey2) {\n const point1 = curve.decodePointHex(publicKey1)\n if (!point1) return false\n\n const point2 = curve.decodePointHex(publicKey2)\n if (!point2) return false\n\n return point1.equals(point2)\n}\n\nmodule.exports = {\n getGlobalCurve,\n generateEcparam,\n generateKeyPairHex,\n compressPublicKeyHex,\n utf8ToHex,\n leftPad,\n arrayToHex,\n arrayToUtf8,\n hexToArray,\n verifyPublicKey,\n comparePublicKeyHex,\n}\n","/* eslint-disable no-case-declarations, max-len */\r\nconst {BigInteger} = require('jsbn')\r\n\r\n/**\r\n * thanks for Tom Wu : http://www-cs-students.stanford.edu/~tjw/jsbn/\r\n *\r\n * Basic Javascript Elliptic Curve implementation\r\n * Ported loosely from BouncyCastle's Java EC code\r\n * Only Fp curves implemented for now\r\n */\r\n\r\nconst TWO = new BigInteger('2')\r\nconst THREE = new BigInteger('3')\r\n\r\n/**\r\n * 椭圆曲线域元素\r\n */\r\nclass ECFieldElementFp {\r\n constructor(q, x) {\r\n this.x = x\r\n this.q = q\r\n // TODO if (x.compareTo(q) >= 0) error\r\n }\r\n\r\n /**\r\n * 判断相等\r\n */\r\n equals(other) {\r\n if (other === this) return true\r\n return (this.q.equals(other.q) && this.x.equals(other.x))\r\n }\r\n\r\n /**\r\n * 返回具体数值\r\n */\r\n toBigInteger() {\r\n return this.x\r\n }\r\n\r\n /**\r\n * 取反\r\n */\r\n negate() {\r\n return new ECFieldElementFp(this.q, this.x.negate().mod(this.q))\r\n }\r\n\r\n /**\r\n * 相加\r\n */\r\n add(b) {\r\n return new ECFieldElementFp(this.q, this.x.add(b.toBigInteger()).mod(this.q))\r\n }\r\n\r\n /**\r\n * 相减\r\n */\r\n subtract(b) {\r\n return new ECFieldElementFp(this.q, this.x.subtract(b.toBigInteger()).mod(this.q))\r\n }\r\n\r\n /**\r\n * 相乘\r\n */\r\n multiply(b) {\r\n return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger()).mod(this.q))\r\n }\r\n\r\n /**\r\n * 相除\r\n */\r\n divide(b) {\r\n return new ECFieldElementFp(this.q, this.x.multiply(b.toBigInteger().modInverse(this.q)).mod(this.q))\r\n }\r\n\r\n /**\r\n * 平方\r\n */\r\n square() {\r\n return new ECFieldElementFp(this.q, this.x.square().mod(this.q))\r\n }\r\n}\r\n\r\nclass ECPointFp {\r\n constructor(curve, x, y, z) {\r\n this.curve = curve\r\n this.x = x\r\n this.y = y\r\n // 标准射影坐标系:zinv == null 或 z * zinv == 1\r\n this.z = z == null ? BigInteger.ONE : z\r\n this.zinv = null\r\n // TODO: compression flag\r\n }\r\n\r\n getX() {\r\n if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)\r\n\r\n return this.curve.fromBigInteger(this.x.toBigInteger().multiply(this.zinv).mod(this.curve.q))\r\n }\r\n\r\n getY() {\r\n if (this.zinv === null) this.zinv = this.z.modInverse(this.curve.q)\r\n\r\n return this.curve.fromBigInteger(this.y.toBigInteger().multiply(this.zinv).mod(this.curve.q))\r\n }\r\n\r\n /**\r\n * 判断相等\r\n */\r\n equals(other) {\r\n if (other === this) return true\r\n if (this.isInfinity()) return other.isInfinity()\r\n if (other.isInfinity()) return this.isInfinity()\r\n\r\n // u = y2 * z1 - y1 * z2\r\n const u = other.y.toBigInteger().multiply(this.z).subtract(this.y.toBigInteger().multiply(other.z)).mod(this.curve.q)\r\n if (!u.equals(BigInteger.ZERO)) return false\r\n\r\n // v = x2 * z1 - x1 * z2\r\n const v = other.x.toBigInteger().multiply(this.z).subtract(this.x.toBigInteger().multiply(other.z)).mod(this.curve.q)\r\n return v.equals(BigInteger.ZERO)\r\n }\r\n\r\n /**\r\n * 是否是无穷远点\r\n */\r\n isInfinity() {\r\n if ((this.x === null) && (this.y === null)) return true\r\n return this.z.equals(BigInteger.ZERO) && !this.y.toBigInteger().equals(BigInteger.ZERO)\r\n }\r\n\r\n /**\r\n * 取反,x 轴对称点\r\n */\r\n negate() {\r\n return new ECPointFp(this.curve, this.x, this.y.negate(), this.z)\r\n }\r\n\r\n /**\r\n * 相加\r\n *\r\n * 标准射影坐标系:\r\n *\r\n * λ1 = x1 * z2\r\n * λ2 = x2 * z1\r\n * λ3 = λ1 − λ2\r\n * λ4 = y1 * z2\r\n * λ5 = y2 * z1\r\n * λ6 = λ4 − λ5\r\n * λ7 = λ1 + λ2\r\n * λ8 = z1 * z2\r\n * λ9 = λ3^2\r\n * λ10 = λ3 * λ9\r\n * λ11 = λ8 * λ6^2 − λ7 * λ9\r\n * x3 = λ3 * λ11\r\n * y3 = λ6 * (λ9 * λ1 − λ11) − λ4 * λ10\r\n * z3 = λ10 * λ8\r\n */\r\n add(b) {\r\n if (this.isInfinity()) return b\r\n if (b.isInfinity()) return this\r\n\r\n const x1 = this.x.toBigInteger()\r\n const y1 = this.y.toBigInteger()\r\n const z1 = this.z\r\n const x2 = b.x.toBigInteger()\r\n const y2 = b.y.toBigInteger()\r\n const z2 = b.z\r\n const q = this.curve.q\r\n\r\n const w1 = x1.multiply(z2).mod(q)\r\n const w2 = x2.multiply(z1).mod(q)\r\n const w3 = w1.subtract(w2)\r\n const w4 = y1.multiply(z2).mod(q)\r\n const w5 = y2.multiply(z1).mod(q)\r\n const w6 = w4.subtract(w5)\r\n\r\n if (BigInteger.ZERO.equals(w3)) {\r\n if (BigInteger.ZERO.equals(w6)) {\r\n return this.twice() // this == b,计算自加\r\n }\r\n return this.curve.infinity // this == -b,则返回无穷远点\r\n }\r\n\r\n const w7 = w1.add(w2)\r\n const w8 = z1.multiply(z2).mod(q)\r\n const w9 = w3.square().mod(q)\r\n const w10 = w3.multiply(w9).mod(q)\r\n const w11 = w8.multiply(w6.square()).subtract(w7.multiply(w9)).mod(q)\r\n\r\n const x3 = w3.multiply(w11).mod(q)\r\n const y3 = w6.multiply(w9.multiply(w1).subtract(w11)).subtract(w4.multiply(w10)).mod(q)\r\n const z3 = w10.multiply(w8).mod(q)\r\n\r\n return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)\r\n }\r\n\r\n /**\r\n * 自加\r\n *\r\n * 标准射影坐标系:\r\n *\r\n * λ1 = 3 * x1^2 + a * z1^2\r\n * λ2 = 2 * y1 * z1\r\n * λ3 = y1^2\r\n * λ4 = λ3 * x1 * z1\r\n * λ5 = λ2^2\r\n * λ6 = λ1^2 − 8 * λ4\r\n * x3 = λ2 * λ6\r\n * y3 = λ1 * (4 * λ4 − λ6) − 2 * λ5 * λ3\r\n * z3 = λ2 * λ5\r\n */\r\n twice() {\r\n if (this.isInfinity()) return this\r\n if (!this.y.toBigInteger().signum()) return this.curve.infinity\r\n\r\n const x1 = this.x.toBigInteger()\r\n const y1 = this.y.toBigInteger()\r\n const z1 = this.z\r\n const q = this.curve.q\r\n const a = this.curve.a.toBigInteger()\r\n\r\n const w1 = x1.square().multiply(THREE).add(a.multiply(z1.square())).mod(q)\r\n const w2 = y1.shiftLeft(1).multiply(z1).mod(q)\r\n const w3 = y1.square().mod(q)\r\n const w4 = w3.multiply(x1).multiply(z1).mod(q)\r\n const w5 = w2.square().mod(q)\r\n const w6 = w1.square().subtract(w4.shiftLeft(3)).mod(q)\r\n\r\n const x3 = w2.multiply(w6).mod(q)\r\n const y3 = w1.multiply(w4.shiftLeft(2).subtract(w6)).subtract(w5.shiftLeft(1).multiply(w3)).mod(q)\r\n const z3 = w2.multiply(w5).mod(q)\r\n\r\n return new ECPointFp(this.curve, this.curve.fromBigInteger(x3), this.curve.fromBigInteger(y3), z3)\r\n }\r\n\r\n /**\r\n * 倍点计算\r\n */\r\n multiply(k) {\r\n if (this.isInfinity()) return this\r\n if (!k.signum()) return this.curve.infinity\r\n\r\n // 使用加减法\r\n const k3 = k.multiply(THREE)\r\n const neg = this.negate()\r\n let Q = this\r\n\r\n for (let i = k3.bitLength() - 2; i > 0; i--) {\r\n Q = Q.twice()\r\n\r\n const k3Bit = k3.testBit(i)\r\n const kBit = k.testBit(i)\r\n\r\n if (k3Bit !== kBit) {\r\n Q = Q.add(k3Bit ? this : neg)\r\n }\r\n }\r\n\r\n return Q\r\n }\r\n}\r\n\r\n/**\r\n * 椭圆曲线 y^2 = x^3 + ax + b\r\n */\r\nclass ECCurveFp {\r\n constructor(q, a, b) {\r\n this.q = q\r\n this.a = this.fromBigInteger(a)\r\n this.b = this.fromBigInteger(b)\r\n this.infinity = new ECPointFp(this, null, null) // 无穷远点\r\n }\r\n\r\n /**\r\n * 判断两个椭圆曲线是否相等\r\n */\r\n equals(other) {\r\n if (other === this) return true\r\n return (this.q.equals(other.q) && this.a.equals(other.a) && this.b.equals(other.b))\r\n }\r\n\r\n /**\r\n * 生成椭圆曲线域元素\r\n */\r\n fromBigInteger(x) {\r\n return new ECFieldElementFp(this.q, x)\r\n }\r\n\r\n /**\r\n * 解析 16 进制串为椭圆曲线点\r\n */\r\n decodePointHex(s) {\r\n switch (parseInt(s.substr(0, 2), 16)) {\r\n // 第一个字节\r\n case 0:\r\n return this.infinity\r\n case 2:\r\n case 3:\r\n // 压缩\r\n const x = this.fromBigInteger(new BigInteger(s.substr(2), 16))\r\n // 对 p ≡ 3 (mod4),即存在正整数 u,使得 p = 4u + 3\r\n // 计算 y = (√ (x^3 + ax + b) % p)^(u + 1) modp\r\n let y = this.fromBigInteger(x.multiply(x.square()).add(\r\n x.multiply(this.a)\r\n ).add(this.b).toBigInteger()\r\n .modPow(\r\n this.q.divide(new BigInteger('4')).add(BigInteger.ONE), this.q\r\n ))\r\n // 算出结果 2 进制最后 1 位不等于第 1 个字节减 2 则取反\r\n if (!y.toBigInteger().mod(TWO).equals(new BigInteger(s.substr(0, 2), 16).subtract(TWO))) {\r\n y = y.negate()\r\n }\r\n return new ECPointFp(this, x, y)\r\n case 4:\r\n case 6:\r\n case 7:\r\n const len = (s.length - 2) / 2\r\n const xHex = s.substr(2, len)\r\n const yHex = s.substr(len + 2, len)\r\n\r\n return new ECPointFp(this, this.fromBigInteger(new BigInteger(xHex, 16)), this.fromBigInteger(new BigInteger(yHex, 16)))\r\n default:\r\n // 不支持\r\n return null\r\n }\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n ECPointFp,\r\n ECCurveFp,\r\n}\r\n","// 消息扩展\nconst W = new Uint32Array(68)\nconst M = new Uint32Array(64) // W'\n\n/**\n * 循环左移\n */\nfunction rotl(x, n) {\n const s = n & 31\n return (x << s) | (x >>> (32 - s))\n}\n\n/**\n * 二进制异或运算\n */\nfunction xor(x, y) {\n const result = []\n for (let i = x.length - 1; i >= 0; i--) result[i] = (x[i] ^ y[i]) & 0xff\n return result\n}\n\n/**\n * 压缩函数中的置换函数 P0(X) = X xor (X <<< 9) xor (X <<< 17)\n */\nfunction P0(X) {\n return (X ^ rotl(X, 9)) ^ rotl(X, 17)\n}\n\n/**\n * 消息扩展中的置换函数 P1(X) = X xor (X <<< 15) xor (X <<< 23)\n */\nfunction P1(X) {\n return (X ^ rotl(X, 15)) ^ rotl(X, 23)\n}\n\n/**\n * sm3 本体\n */\nfunction sm3(array) {\n let len = array.length * 8\n\n // k 是满足 len + 1 + k = 448mod512 的最小的非负整数\n let k = len % 512\n // 如果 448 <= (512 % len) < 512,需要多补充 (len % 448) 比特'0'以满足总比特长度为512的倍数\n k = k >= 448 ? 512 - (k % 448) - 1 : 448 - k - 1\n\n // 填充\n const kArr = new Array((k - 7) / 8)\n const lenArr = new Array(8)\n for (let i = 0, len = kArr.length; i < len; i++) kArr[i] = 0\n for (let i = 0, len = lenArr.length; i < len; i++) lenArr[i] = 0\n len = len.toString(2)\n for (let i = 7; i >= 0; i--) {\n if (len.length > 8) {\n const start = len.length - 8\n lenArr[i] = parseInt(len.substr(start), 2)\n len = len.substr(0, start)\n } else if (len.length > 0) {\n lenArr[i] = parseInt(len, 2)\n len = ''\n }\n }\n const m = new Uint8Array([...array, 0x80, ...kArr, ...lenArr])\n const dataView = new DataView(m.buffer, 0)\n\n // 迭代压缩\n const n = m.length / 64\n const V = new Uint32Array([0x7380166f, 0x4914b2b9, 0x172442d7, 0xda8a0600, 0xa96f30bc, 0x163138aa, 0xe38dee4d, 0xb0fb0e4e])\n for (let i = 0; i < n; i++) {\n W.fill(0)\n M.fill(0)\n\n // 将消息分组B划分为 16 个字 W0, W1,……,W15\n const start = 16 * i\n for (let j = 0; j < 16; j++) {\n W[j] = dataView.getUint32((start + j) * 4, false)\n }\n\n // W16 ~ W67:W[j] <- P1(W[j−16] xor W[j−9] xor (W[j−3] <<< 15)) xor (W[j−13] <<< 7) xor W[j−6]\n for (let j = 16; j < 68; j++) {\n W[j] = (P1((W[j - 16] ^ W[j - 9]) ^ rotl(W[j - 3], 15)) ^ rotl(W[j - 13], 7)) ^ W[j - 6]\n }\n\n // W′0 ~ W′63:W′[j] = W[j] xor W[j+4]\n for (let j = 0; j < 64; j++) {\n M[j] = W[j] ^ W[j + 4]\n }\n\n // 压缩\n const T1 = 0x79cc4519\n const T2 = 0x7a879d8a\n // 字寄存器\n let A = V[0]\n let B = V[1]\n let C = V[2]\n let D = V[3]\n let E = V[4]\n let F = V[5]\n let G = V[6]\n let H = V[7]\n // 中间变量\n let SS1\n let SS2\n let TT1\n let TT2\n let T\n for (let j = 0; j < 64; j++) {\n T = j >= 0 && j <= 15 ? T1 : T2\n SS1 = rotl(rotl(A, 12) + E + rotl(T, j), 7)\n SS2 = SS1 ^ rotl(A, 12)\n\n TT1 = (j >= 0 && j <= 15 ? ((A ^ B) ^ C) : (((A & B) | (A & C)) | (B & C))) + D + SS2 + M[j]\n TT2 = (j >= 0 && j <= 15 ? ((E ^ F) ^ G) : ((E & F) | ((~E) & G))) + H + SS1 + W[j]\n\n D = C\n C = rotl(B, 9)\n B = A\n A = TT1\n H = G\n G = rotl(F, 19)\n F = E\n E = P0(TT2)\n }\n\n V[0] ^= A\n V[1] ^= B\n V[2] ^= C\n V[3] ^= D\n V[4] ^= E\n V[5] ^= F\n V[6] ^= G\n V[7] ^= H\n }\n\n // 转回 uint8\n const result = []\n for (let i = 0, len = V.length; i < len; i++) {\n const word = V[i]\n result.push((word & 0xff000000) >>> 24, (word & 0xff0000) >>> 16, (word & 0xff00) >>> 8, word & 0xff)\n }\n\n return result\n}\n\n/**\n * hmac 实现\n */\nconst blockLen = 64\nconst iPad = new Uint8Array(blockLen)\nconst oPad = new Uint8Array(blockLen)\nfor (let i = 0; i < blockLen; i++) {\n iPad[i] = 0x36\n oPad[i] = 0x5c\n}\nfunction hmac(input, key) {\n // 密钥填充\n if (key.length > blockLen) key = sm3(key)\n while (key.length < blockLen) key.push(0)\n\n const iPadKey = xor(key, iPad)\n const oPadKey = xor(key, oPad)\n\n const hash = sm3([...iPadKey, ...input])\n return sm3([...oPadKey, ...hash])\n}\n\nmodule.exports = {\n sm3,\n hmac,\n}\n","const {sm3, hmac} = require('../sm2/sm3')\n\n/**\n * 补全16进制字符串\n */\nfunction leftPad(input, num) {\n if (input.length >= num) return input\n\n return (new Array(num - input.length + 1)).join('0') + input\n}\n\n/**\n * 字节数组转 16 进制串\n */\nfunction ArrayToHex(arr) {\n return arr.map(item => {\n item = item.toString(16)\n return item.length === 1 ? '0' + item : item\n }).join('')\n}\n\n/**\n * 转成字节数组\n */\nfunction hexToArray(hexStr) {\n const words = []\n let hexStrLength = hexStr.length\n\n if (hexStrLength % 2 !== 0) {\n hexStr = leftPad(hexStr, hexStrLength + 1)\n }\n\n hexStrLength = hexStr.length\n\n for (let i = 0; i < hexStrLength; i += 2) {\n words.push(parseInt(hexStr.substr(i, 2), 16))\n }\n return words\n}\n\n/**\n * utf8 串转字节数组\n */\nfunction utf8ToArray(str) {\n const arr = []\n\n for (let i = 0, len = str.length; i < len; i++) {\n const point = str.codePointAt(i)\n\n if (point <= 0x007f) {\n // 单字节,标量值:00000000 00000000 0zzzzzzz\n arr.push(point)\n } else if (point <= 0x07ff) {\n // 双字节,标量值:00000000 00000yyy yyzzzzzz\n arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)\n arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)\n } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {\n // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz\n arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)\n arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)\n arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)\n } else if (point >= 0x010000 && point <= 0x10FFFF) {\n // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz\n i++\n arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)\n arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)\n arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)\n arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)\n } else {\n // 五、六字节,暂时不支持\n arr.push(point)\n throw new Error('input is not supported')\n }\n }\n\n return arr\n}\n\nmodule.exports = function (input, options) {\n input = typeof input === 'string' ? utf8ToArray(input) : Array.prototype.slice.call(input)\n\n if (options) {\n const mode = options.mode || 'hmac'\n if (mode !== 'hmac') throw new Error('invalid mode')\n\n let key = options.key\n if (!key) throw new Error('invalid key')\n\n key = typeof key === 'string' ? hexToArray(key) : Array.prototype.slice.call(key)\n return ArrayToHex(hmac(input, key))\n }\n\n return ArrayToHex(sm3(input))\n}\n","/* eslint-disable no-bitwise, no-mixed-operators, complexity */\r\nconst DECRYPT = 0\r\nconst ROUND = 32\r\nconst BLOCK = 16\r\n\r\nconst Sbox = [\r\n 0xd6, 0x90, 0xe9, 0xfe, 0xcc, 0xe1, 0x3d, 0xb7, 0x16, 0xb6, 0x14, 0xc2, 0x28, 0xfb, 0x2c, 0x05,\r\n 0x2b, 0x67, 0x9a, 0x76, 0x2a, 0xbe, 0x04, 0xc3, 0xaa, 0x44, 0x13, 0x26, 0x49, 0x86, 0x06, 0x99,\r\n 0x9c, 0x42, 0x50, 0xf4, 0x91, 0xef, 0x98, 0x7a, 0x33, 0x54, 0x0b, 0x43, 0xed, 0xcf, 0xac, 0x62,\r\n 0xe4, 0xb3, 0x1c, 0xa9, 0xc9, 0x08, 0xe8, 0x95, 0x80, 0xdf, 0x94, 0xfa, 0x75, 0x8f, 0x3f, 0xa6,\r\n 0x47, 0x07, 0xa7, 0xfc, 0xf3, 0x73, 0x17, 0xba, 0x83, 0x59, 0x3c, 0x19, 0xe6, 0x85, 0x4f, 0xa8,\r\n 0x68, 0x6b, 0x81, 0xb2, 0x71, 0x64, 0xda, 0x8b, 0xf8, 0xeb, 0x0f, 0x4b, 0x70, 0x56, 0x9d, 0x35,\r\n 0x1e, 0x24, 0x0e, 0x5e, 0x63, 0x58, 0xd1, 0xa2, 0x25, 0x22, 0x7c, 0x3b, 0x01, 0x21, 0x78, 0x87,\r\n 0xd4, 0x00, 0x46, 0x57, 0x9f, 0xd3, 0x27, 0x52, 0x4c, 0x36, 0x02, 0xe7, 0xa0, 0xc4, 0xc8, 0x9e,\r\n 0xea, 0xbf, 0x8a, 0xd2, 0x40, 0xc7, 0x38, 0xb5, 0xa3, 0xf7, 0xf2, 0xce, 0xf9, 0x61, 0x15, 0xa1,\r\n 0xe0, 0xae, 0x5d, 0xa4, 0x9b, 0x34, 0x1a, 0x55, 0xad, 0x93, 0x32, 0x30, 0xf5, 0x8c, 0xb1, 0xe3,\r\n 0x1d, 0xf6, 0xe2, 0x2e, 0x82, 0x66, 0xca, 0x60, 0xc0, 0x29, 0x23, 0xab, 0x0d, 0x53, 0x4e, 0x6f,\r\n 0xd5, 0xdb, 0x37, 0x45, 0xde, 0xfd, 0x8e, 0x2f, 0x03, 0xff, 0x6a, 0x72, 0x6d, 0x6c, 0x5b, 0x51,\r\n 0x8d, 0x1b, 0xaf, 0x92, 0xbb, 0xdd, 0xbc, 0x7f, 0x11, 0xd9, 0x5c, 0x41, 0x1f, 0x10, 0x5a, 0xd8,\r\n 0x0a, 0xc1, 0x31, 0x88, 0xa5, 0xcd, 0x7b, 0xbd, 0x2d, 0x74, 0xd0, 0x12, 0xb8, 0xe5, 0xb4, 0xb0,\r\n 0x89, 0x69, 0x97, 0x4a, 0x0c, 0x96, 0x77, 0x7e, 0x65, 0xb9, 0xf1, 0x09, 0xc5, 0x6e, 0xc6, 0x84,\r\n 0x18, 0xf0, 0x7d, 0xec, 0x3a, 0xdc, 0x4d, 0x20, 0x79, 0xee, 0x5f, 0x3e, 0xd7, 0xcb, 0x39, 0x48\r\n]\r\n\r\nconst CK = [\r\n 0x00070e15, 0x1c232a31, 0x383f464d, 0x545b6269,\r\n 0x70777e85, 0x8c939aa1, 0xa8afb6bd, 0xc4cbd2d9,\r\n 0xe0e7eef5, 0xfc030a11, 0x181f262d, 0x343b4249,\r\n 0x50575e65, 0x6c737a81, 0x888f969d, 0xa4abb2b9,\r\n 0xc0c7ced5, 0xdce3eaf1, 0xf8ff060d, 0x141b2229,\r\n 0x30373e45, 0x4c535a61, 0x686f767d, 0x848b9299,\r\n 0xa0a7aeb5, 0xbcc3cad1, 0xd8dfe6ed, 0xf4fb0209,\r\n 0x10171e25, 0x2c333a41, 0x484f565d, 0x646b7279\r\n]\r\n\r\n/**\r\n * 16 进制串转字节数组\r\n */\r\nfunction hexToArray(str) {\r\n const arr = []\r\n for (let i = 0, len = str.length; i < len; i += 2) {\r\n arr.push(parseInt(str.substr(i, 2), 16))\r\n }\r\n return arr\r\n}\r\n\r\n/**\r\n * 字节数组转 16 进制串\r\n */\r\nfunction ArrayToHex(arr) {\r\n return arr.map(item => {\r\n item = item.toString(16)\r\n return item.length === 1 ? '0' + item : item\r\n }).join('')\r\n}\r\n\r\n/**\r\n * utf8 串转字节数组\r\n */\r\nfunction utf8ToArray(str) {\r\n const arr = []\r\n\r\n for (let i = 0, len = str.length; i < len; i++) {\r\n const point = str.codePointAt(i)\r\n\r\n if (point <= 0x007f) {\r\n // 单字节,标量值:00000000 00000000 0zzzzzzz\r\n arr.push(point)\r\n } else if (point <= 0x07ff) {\r\n // 双字节,标量值:00000000 00000yyy yyzzzzzz\r\n arr.push(0xc0 | (point >>> 6)) // 110yyyyy(0xc0-0xdf)\r\n arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)\r\n } else if (point <= 0xD7FF || (point >= 0xE000 && point <= 0xFFFF)) {\r\n // 三字节:标量值:00000000 xxxxyyyy yyzzzzzz\r\n arr.push(0xe0 | (point >>> 12)) // 1110xxxx(0xe0-0xef)\r\n arr.push(0x80 | ((point >>> 6) & 0x3f)) // 10yyyyyy(0x80-0xbf)\r\n arr.push(0x80 | (point & 0x3f)) // 10zzzzzz(0x80-0xbf)\r\n } else if (point >= 0x010000 && point <= 0x10FFFF) {\r\n // 四字节:标量值:000wwwxx xxxxyyyy yyzzzzzz\r\n i++\r\n arr.push((0xf0 | (point >>> 18) & 0x1c)) // 11110www(0xf0-0xf7)\r\n arr.push((0x80 | ((point >>> 12) & 0x3f))) // 10xxxxxx(0x80-0xbf)\r\n arr.push((0x80 | ((point >>> 6) & 0x3f))) // 10yyyyyy(0x80-0xbf)\r\n arr.push((0x80 | (point & 0x3f))) // 10zzzzzz(0x80-0xbf)\r\n } else {\r\n // 五、六字节,暂时不支持\r\n arr.push(point)\r\n throw new Error('input is not supported')\r\n }\r\n }\r\n\r\n return arr\r\n}\r\n\r\n/**\r\n * 字节数组转 utf8 串\r\n */\r\nfunction arrayToUtf8(arr) {\r\n const str = []\r\n for (let i = 0, len = arr.length; i < len; i++) {\r\n if (arr[i] >= 0xf0 && arr[i] <= 0xf7) {\r\n // 四字节\r\n str.push(String.fromCodePoint(((arr[i] & 0x07) << 18) + ((arr[i + 1] & 0x3f) << 12) + ((arr[i + 2] & 0x3f) << 6) + (arr[i + 3] & 0x3f)))\r\n i += 3\r\n } else if (arr[i] >= 0xe0 && arr[i] <= 0xef) {\r\n // 三字节\r\n str.push(String.fromCodePoint(((arr[i] & 0x0f) << 12) + ((arr[i + 1] & 0x3f) << 6) + (arr[i + 2] & 0x3f)))\r\n i += 2\r\n } else if (arr[i] >= 0xc0 && arr[i] <= 0xdf) {\r\n // 双字节\r\n str.push(String.fromCodePoint(((arr[i] & 0x1f) << 6) + (arr[i + 1] & 0x3f)))\r\n i++\r\n } else {\r\n // 单字节\r\n str.push(String.fromCodePoint(arr[i]))\r\n }\r\n }\r\n\r\n return str.join('')\r\n}\r\n\r\n/**\r\n * 32 比特循环左移\r\n */\r\nfunction rotl(x, n) {\r\n const s = n & 31\r\n return (x << s) | (x >>> (32 - s))\r\n}\r\n\r\n/**\r\n * 非线性变换\r\n */\r\nfunction byteSub(a) {\r\n return (Sbox[a >>> 24 & 0xFF] & 0xFF) << 24 |\r\n (Sbox[a >>> 16 & 0xFF] & 0xFF) << 16 |\r\n (Sbox[a >>> 8 & 0xFF] & 0xFF) << 8 |\r\n (Sbox[a & 0xFF] & 0xFF)\r\n}\r\n\r\n/**\r\n * 线性变换,加密/解密用\r\n */\r\nfunction l1(b) {\r\n return b ^ rotl(b, 2) ^ rotl(b, 10) ^ rotl(b, 18) ^ rotl(b, 24)\r\n}\r\n\r\n/**\r\n * 线性变换,生成轮密钥用\r\n */\r\nfunction l2(b) {\r\n return b ^ rotl(b, 13) ^ rotl(b, 23)\r\n}\r\n\r\n/**\r\n * 以一组 128 比特进行加密/解密操作\r\n */\r\nfunction sms4Crypt(input, output, roundKey) {\r\n const x = new Array(4)\r\n\r\n // 字节数组转成字数组(此处 1 字 = 32 比特)\r\n const tmp = new Array(4)\r\n for (let i = 0; i < 4; i++) {\r\n tmp[0] = input[4 * i] & 0xff\r\n tmp[1] = input[4 * i + 1] & 0xff\r\n tmp[2] = input[4 * i + 2] & 0xff\r\n tmp[3] = input[4 * i + 3] & 0xff\r\n x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]\r\n }\r\n\r\n // x[i + 4] = x[i] ^ l1(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ roundKey[i]))\r\n for (let r = 0, mid; r < 32; r += 4) {\r\n mid = x[1] ^ x[2] ^ x[3] ^ roundKey[r + 0]\r\n x[0] ^= l1(byteSub(mid)) // x[4]\r\n\r\n mid = x[2] ^ x[3] ^ x[0] ^ roundKey[r + 1]\r\n x[1] ^= l1(byteSub(mid)) // x[5]\r\n\r\n mid = x[3] ^ x[0] ^ x[1] ^ roundKey[r + 2]\r\n x[2] ^= l1(byteSub(mid)) // x[6]\r\n\r\n mid = x[0] ^ x[1] ^ x[2] ^ roundKey[r + 3]\r\n x[3] ^= l1(byteSub(mid)) // x[7]\r\n }\r\n\r\n // 反序变换\r\n for (let j = 0; j < 16; j += 4) {\r\n output[j] = x[3 - j / 4] >>> 24 & 0xff\r\n output[j + 1] = x[3 - j / 4] >>> 16 & 0xff\r\n output[j + 2] = x[3 - j / 4] >>> 8 & 0xff\r\n output[j + 3] = x[3 - j / 4] & 0xff\r\n }\r\n}\r\n\r\n/**\r\n * 密钥扩展算法\r\n */\r\nfunction sms4KeyExt(key, roundKey, cryptFlag) {\r\n const x = new Array(4)\r\n\r\n // 字节数组转成字数组(此处 1 字 = 32 比特)\r\n const tmp = new Array(4)\r\n for (let i = 0; i < 4; i++) {\r\n tmp[0] = key[0 + 4 * i] & 0xff\r\n tmp[1] = key[1 + 4 * i] & 0xff\r\n tmp[2] = key[2 + 4 * i] & 0xff\r\n tmp[3] = key[3 + 4 * i] & 0xff\r\n x[i] = tmp[0] << 24 | tmp[1] << 16 | tmp[2] << 8 | tmp[3]\r\n }\r\n\r\n // 与系统参数做异或\r\n x[0] ^= 0xa3b1bac6\r\n x[1] ^= 0x56aa3350\r\n x[2] ^= 0x677d9197\r\n x[3] ^= 0xb27022dc\r\n\r\n // roundKey[i] = x[i + 4] = x[i] ^ l2(byteSub(x[i + 1] ^ x[i + 2] ^ x[i + 3] ^ CK[i]))\r\n for (let r = 0, mid; r < 32; r += 4) {\r\n mid = x[1] ^ x[2] ^ x[3] ^ CK[r + 0]\r\n roundKey[r + 0] = x[0] ^= l2(byteSub(mid)) // x[4]\r\n\r\n mid = x[2] ^ x[3] ^ x[0] ^ CK[r + 1]\r\n roundKey[r + 1] = x[1] ^= l2(byteSub(mid)) // x[5]\r\n\r\n mid = x[3] ^ x[0] ^ x[1] ^ CK[r + 2]\r\n roundKey[r + 2] = x[2] ^= l2(byteSub(mid)) // x[6]\r\n\r\n mid = x[0] ^ x[1] ^ x[2] ^ CK[r + 3]\r\n roundKey[r + 3] = x[3] ^= l2(byteSub(mid)) // x[7]\r\n }\r\n\r\n // 解密时使用反序的轮密钥\r\n if (cryptFlag === DECRYPT) {\r\n for (let r = 0, mid; r < 16; r++) {\r\n mid = roundKey[r]\r\n roundKey[r] = roundKey[31 - r]\r\n roundKey[31 - r] = mid\r\n }\r\n }\r\n}\r\n\r\nfunction sm4(inArray, key, cryptFlag, {\r\n padding = 'pkcs#7', mode, iv = [], output = 'string'\r\n} = {}) {\r\n if (mode === 'cbc') {\r\n // CBC 模式,默认走 ECB 模式\r\n if (typeof iv === 'string') iv = hexToArray(iv)\r\n if (iv.length !== (128 / 8)) {\r\n // iv 不是 128 比特\r\n throw new Error('iv is invalid')\r\n }\r\n }\r\n\r\n // 检查 key\r\n if (typeof key === 'string') key = hexToArray(key)\r\n if (key.length !== (128 / 8)) {\r\n // key 不是 128 比特\r\n throw new Error('key is invalid')\r\n }\r\n\r\n // 检查输入\r\n if (typeof inArray === 'string') {\r\n if (cryptFlag !== DECRYPT) {\r\n // 加密,输入为 utf8 串\r\n inArray = utf8ToArray(inArray)\r\n } else {\r\n // 解密,输入为 16 进制串\r\n inArray = hexToArray(inArray)\r\n }\r\n } else {\r\n inArray = [...inArray]\r\n }\r\n\r\n // 新增填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7\r\n if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag !== DECRYPT) {\r\n const paddingCount = BLOCK - inArray.length % BLOCK\r\n for (let i = 0; i < paddingCount; i++) inArray.push(paddingCount)\r\n }\r\n\r\n // 生成轮密钥\r\n const roundKey = new Array(ROUND)\r\n sms4KeyExt(key, roundKey, cryptFlag)\r\n\r\n const outArray = []\r\n let lastVector = iv\r\n let restLen = inArray.length\r\n let point = 0\r\n while (restLen >= BLOCK) {\r\n const input = inArray.slice(point, point + 16)\r\n const output = new Array(16)\r\n\r\n if (mode === 'cbc') {\r\n for (let i = 0; i < BLOCK; i++) {\r\n if (cryptFlag !== DECRYPT) {\r\n // 加密过程在组加密前进行异或\r\n input[i] ^= lastVector[i]\r\n }\r\n }\r\n }\r\n\r\n sms4Crypt(input, output, roundKey)\r\n\r\n\r\n for (let i = 0; i < BLOCK; i++) {\r\n if (mode === 'cbc') {\r\n if (cryptFlag === DECRYPT) {\r\n // 解密过程在组解密后进行异或\r\n output[i] ^= lastVector[i]\r\n }\r\n }\r\n\r\n outArray[point + i] = output[i]\r\n }\r\n\r\n if (mode === 'cbc') {\r\n if (cryptFlag !== DECRYPT) {\r\n // 使用上一次输出作为加密向量\r\n lastVector = output\r\n } else {\r\n // 使用上一次输入作为解密向量\r\n lastVector = input\r\n }\r\n }\r\n\r\n restLen -= BLOCK\r\n point += BLOCK\r\n }\r\n\r\n // 去除填充,sm4 是 16 个字节一个分组,所以统一走到 pkcs#7\r\n if ((padding === 'pkcs#5' || padding === 'pkcs#7') && cryptFlag === DECRYPT) {\r\n const len = outArray.length\r\n const paddingCount = outArray[len - 1]\r\n for (let i = 1; i <= paddingCount; i++) {\r\n if (outArray[len - i] !== paddingCount) throw new Error('padding is invalid')\r\n }\r\n outArray.splice(len - paddingCount, paddingCount)\r\n }\r\n\r\n // 调整输出\r\n if (output !== 'array') {\r\n if (cryptFlag !== DECRYPT) {\r\n // 加密,输出转 16 进制串\r\n return ArrayToHex(outArray)\r\n } else {\r\n // 解密,输出转 utf8 串\r\n return arrayToUtf8(outArray)\r\n }\r\n } else {\r\n return outArray\r\n }\r\n}\r\n\r\nmodule.exports = {\r\n encrypt(inArray, key, options) {\r\n return sm4(inArray, key, 1, options)\r\n },\r\n decrypt(inArray, key, options) {\r\n return sm4(inArray, key, 0, options)\r\n }\r\n}\r\n"]}
\ No newline at end of file
{
"name": "package.json",
"version": "1.0.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
"charenc": {
"version": "0.0.2",
"resolved": "https://registry.npmmirror.com/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA=="
},
"chinese-lunar-calendar": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/chinese-lunar-calendar/-/chinese-lunar-calendar-1.0.1.tgz",
"integrity": "sha512-T5XjtA6ygOkxjwltYf8dEB1DLsPKewDKajf74fNeT6rH2g9EZPf2AHk6vAlK/SAImTYKXoUNQ3Q4JwN0BduqRA=="
},
"crypt": {
"version": "0.0.2",
"resolved": "https://registry.npmmirror.com/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow=="
},
"dayjs": {
"version": "1.11.13",
"resolved": "https://registry.npmmirror.com/dayjs/-/dayjs-1.11.13.tgz",
"integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg=="
},
"is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmmirror.com/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"jsbn": {
"version": "1.1.0",
"resolved": "https://registry.npmmirror.com/jsbn/-/jsbn-1.1.0.tgz",
"integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A=="
},
"md5": {
"version": "2.3.0",
"resolved": "https://registry.npmmirror.com/md5/-/md5-2.3.0.tgz",
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
"requires": {
"charenc": "0.0.2",
"crypt": "0.0.2",
"is-buffer": "~1.1.6"
}
},
"moment": {
"version": "2.30.1",
"resolved": "https://registry.npmmirror.com/moment/-/moment-2.30.1.tgz",
"integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how=="
},
"sm-crypto": {
"version": "0.3.13",
"resolved": "https://registry.npmmirror.com/sm-crypto/-/sm-crypto-0.3.13.tgz",
"integrity": "sha512-ztNF+pZq6viCPMA1A6KKu3bgpkmYti5avykRHbcFIdSipFdkVmfUw2CnpM2kBJyppIalqvczLNM3wR8OQ0pT5w==",
"requires": {
"jsbn": "^1.1.0"
}
}
}
}
{
"name": "package.json",
"version": "1.0.0",
"description": "小程序开发",
"repository": {
"type": "git",
"url": "git+https://github.com/yourusername/your-repo-name.git"
},
"main": ".eslintrc.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"chinese-lunar-calendar": "^1.0.1",
"dayjs": "^1.11.13",
"md5": "^2.3.0",
"moment": "^2.30.1",
"sm-crypto": "^0.3.13"
},
"bugs": {
"url": "https://github.com/yourusername/your-repo-name/issues"
},
"homepage": "https://github.com/yourusername/your-repo-name#readme",
"devDependencies": {},
"keywords": []
}
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
relationId: '',
relationName:'',
level:'',
typeTwo:'',
typeThree:'',
navList: [],
childNavList: [],
newsList: [],
current: 0,
childCurrent: null,
branchStyle:[
{
imgUrl:'https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=zbfc3.png',
name:'系统运行党支部',
personNum:"12人",
time:"2023-10-23",
detail:'支部成立于2023年,日常主要承担虹桥机场网络、离港、航显、集成、视频监控等相关信息系统的运维工作,在日常工作中勇于创新,取得多项行业专利证书。'
},
{
imgUrl:'https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=zbfc4.png',
name:'机电运行党支部',
personNum:"16人",
time:"2023-10-23",
detail:'支部成立于2023年,日常主要承担虹桥机场登机桥、行李等相关机电设备的运维工作,并曾多次在民航业的登机桥技能大赛中取得好成绩。'
},
{
imgUrl:'https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=zbfc2.png',
name:'安控管理党支部',
personNum:"20人",
time:"2024-04-18",
detail:'支部成立于2018年,主要负责保障部的运行指挥、协同处置以及安全、服务、舆情、应急管理等条线工作。'
},
{
imgUrl:'https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=zbfc1.png',
name:'设备工程党支部',
personNum:"20人(含1名预备党员)",
time:"2024.04.11",
detail:'支部成立于2018年,2020年成为虹桥公司基层党建示范点。部室内党员比例高达50%,日常主要承担虹桥机场离港、航显、集成、视频监控、行李、登机桥等相关系统的数字化、智慧化应用和建设,以及相关设备条线的管理工作。'
},
{
imgUrl:'https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=zbfc5.png',
name:'机关、业务、IT党支部',
personNum:"21人",
time:"2024-04-11",
detail:'支部成立于2018年,日常主要承担保障部综合事务、业务招标采购、合同管理、IT项目建设、网络安全以及党纪工团等条线工作。'
}
],//支部风采
},
// 生命周期函数
onLoad: function (option) {
wx.setNavigationBarTitle({
title: option.relationName,
});
this.setData({
relationId: option.id,
relationName:option.relationName
})
let params = {
level: this.data.level,
pageNo: '1',
pageSize: '50',
relationId: this.data.relationId,
terminalName: 'MOBILE',
typeName: 'news',
typeTwo:this.data.typeTwo,
}
post(url.NewsMessageApi, params).then(res => {
let childNav = res.data.classifyNews[0].childClassifyNews
let childNum = res.data.classifyNews[0].id
this.setData({
navList: res.data.classifyNews,
childNavList:childNav,
level:'2',
typeTwo:childNum
})
this.getNewsList()
})
},
getNewsList: function () {
let params = {
level: this.data.level,
pageNo: '1',
pageSize: '50',
relationId: this.data.relationId,
terminalName: 'MOBILE',
typeName: 'news',
typeTwo:this.data.typeTwo,
}
post(url.NewsMessageApi, params).then(res => {
res.data.news.map((item) => {
item.releaseTime = moment(item.releaseTime).format("YYYY-MM-DD")
})
this.setData({
newsList: res.data.news,
})
})
},
currentNav: function (e) {
let index = e.currentTarget.dataset.index;
let childNav = this.data.navList[index].childClassifyNews;
let childId = this.data.navList[index].id;
this.setData({
current: index,
childNavList:childNav,
level:'2',
typeTwo:childId,
childCurrent:null
})
this.getNewsList()
},
currentChildNav: function (e) {
let index = e.currentTarget.dataset.index;
let childId= this.data.childNavList[index].id
this.setData({
childCurrent: index,
level:'3',
typeTwo:childId
})
this.getNewsList()
},
handleTo: function (e) {
let item = e.currentTarget.dataset.item;
wx.navigateTo({
url: '/pages/NewsMessage/news/index?id='+item.id,
})
},
});
\ No newline at end of file
{
"usingComponents": {}
}
\ No newline at end of file
<!--pages/NewsMessage/index.wxml-->
<view>
<scroll-view scroll-x="true" enable-flex="true" enhanced="true" show-scrollbar="false" class="scroll-view_H">
<block wx:for="{{ navList }}" wx:for-index="index" wx:key="index">
<view class="nav-item {{ current==index?'current-nav':'' }}" bindtap="currentNav" data-index="{{ index }}">
{{ item.name }}
</view>
</block>
</scroll-view>
<view class="child-nav">
<block wx:for="{{ childNavList }}" wx:for-index="index" wx:key="index">
<view class="childNav-item {{ childCurrent==index?'childCurrent-navActive':'childCurrent-nav' }}" bindtap="currentChildNav" data-index="{{ index }}">
{{ item.name }}
</view>
</block>
</view>
<view class="branch-out" wx:if="{{relationName=='支部风采'}}">
<view style="color: #fff;">支部介绍</view>
<image src="{{branchStyle[current].imgUrl}}" mode="widthFix" style="width: 100%;height: 200px;margin-top: 20px;"/>
<view class="branch-tit">{{branchStyle[current].name}}</view>
<view style="display: flex;">
<view class="branch-num">党员人数 {{branchStyle[current].personNum}}</view>
<view class="branch-time">上次换届时间 {{branchStyle[current].time}}</view>
</view>
<view class="branch-detail">{{branchStyle[current].detail}}</view>
</view>
<view class="new-out">
<block wx:for="{{ newsList }}" wx:key="id" wx:for-index="index">
<view class="new-list" bindtap="handleTo" data-item="{{ item }}">
<image wx:if="{{item.logoPath}}" style="width: 40%;height:100px;" src="{{item.logoPath}}" mode="scaleToFill" />
<view class="new-item">
<view class="new-font">{{item.fileName}}</view>
<view style="color: #999;font-size: 12px;">
{{item.releaseTime}}
</view>
</view>
</view>
</block>
</view>
</view>
\ No newline at end of file
/* 一级滚动菜单 */
.scroll-view_H {
width: 100%;
display: flex;
background-color: #D23A29;
height: 40px;
line-height: 40px;
white-space: nowrap;
margin-bottom: 4px;
padding-bottom: 5px;
}
/* // 隐藏滚动条1 */
::-webkit-scrollbar {
display: none;
width: 0;
height: 0;
color: transparent;
}
.nav-item {
height: 35px;
margin-right: 20rpx;
margin-left: 20rpx;
color: #fff;
}
/* 添加下边界 */
.current-nav {
border-bottom: 2px solid #fff;
}
/* 二级菜单 */
.child-nav {
width: 92%;
margin: 0 auto;
display: flex;
margin-bottom: 15px;
}
.childNav-item {
padding: 4px 12px;
border-radius: 2px;
margin-right: 10px;
}
.childCurrent-nav {
background: #f7f7f7;
color: #454343;
}
.childCurrent-navActive {
background: #ffebeb;
color: #D23A29;
}
/* 新闻信息 */
.new-out {
width: 90%;
margin: 10px auto;
padding-bottom: 20px;
}
.new-list {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.new-font {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
}
.new-item {
width: 58%;
height: 95px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
/* 支部风采 */
.branch-out {
width: 90%;
margin: 10px auto;
padding: 3px 10px 8px;
background-image: url('https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=20250411094624.png');
background-size: 100%;
background-repeat: no-repeat;
box-sizing: border-box;
}
.branch-tit {
font-weight: bold;
margin-top: 10px;
margin-bottom: 10px;
}
.branch-num {
font-size: 12px;
padding: 2px 4px;
background: #e7f7e8;
border: 1px solid rgba(120, 193, 127, 0.10);
border-radius: 2px;
color: #53AF5C;
margin-right: 5px;
}
.branch-time {
font-size: 12px;
padding: 2px 4px;
background: #fff5ed;
border: 1px solid rgba(255, 152, 56, 0.10);
border-radius: 2px;
color: #F5912A;
}
.branch-detail{
margin-top: 10px;
font-size: 14px;
color: #333647;
}
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
const {
formatRichText
} = require('../../../utils/util')
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
newsList: {},
favoriteState: "",
formatText: '',
newsId: ''
},
// 生命周期函数
onLoad: function (option) {
let params = {
id: option.id
}
post(url.NewsResultListApi, params).then(res => {
res.data.releaseTime = moment(res.data.releaseTime).format("YYYY-MM-DD")
this.setData({
newsList: res.data,
favoriteState: res.data.favoriteState,
newsId: option.id,
formatText: formatRichText(res.data.content)
})
})
},
});
\ No newline at end of file
{
"usingComponents": {
"my-comment":"/pages/components/comment/index"
},
"navigationBarTitleText": "资讯详情"
}
\ No newline at end of file
<!--pages/NewsMessage/news/index.wxml-->
<view style="padding-bottom: 30px;">
<!-- 标题 -->
<view class="news-item2-box">
<view class="title-span">{{newsList.fileName}}</view>
<view class="title-p">
<text>来源 {{newsList.author}} | {{newsList.releaseTime}}</text>
<text>阅读 {{newsList.readCount}}</text>
</view>
</view>
<!-- //文章 -->
<view style="width: 92%;margin:0 auto;">
<rich-text nodes="{{formatText}}"></rich-text>
</view>
<!-- 评论 -->
<view>
<my-comment uploadImgStu="{{false}}" newsId="{{newsId}}" favoriteState="{{favoriteState}}" favoriteShow="{{true}}" bizType="{{1}}"></my-comment>
</view>
</view>
\ No newline at end of file
.image_class {
max-width: 100%;
margin: 4px auto;
}
.span_class {
line-height: 20px;
}
.news-item2-box {
width: 100%;
}
.title-span {
display: block;
font-size: 20px;
margin-left: 5%;
margin-top: 5%;
width: 90%;
font-weight: 500;
color: #000;
line-height: 48px;
}
.title-p {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
color: #ABABAB;
padding: 5%;
font-size: 12px;
box-sizing: border-box;
}
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
const moment = require('/miniprogram_npm/moment/index.js');
const {
formatRichText
} = require('../../../utils/util')
Page({
data: {
newsId: '',
activeData: {}
},
onLoad: function (options) {
this.setData({
newsId: options.id,
})
this.getActiveDetail()
},
getActiveDetail() {
post(url.getActiveDetailApi, {
id: this.options.id
}).then(res => {
let obj = res.data.introductionVo;
obj.startTime = moment(obj.startTime).format("YYYY-MM-DD HH:mm");
obj.endTime = moment(obj.endTime).format("YYYY-MM-DD HH:mm")
obj.description = formatRichText(obj.description)
this.setData({
activeData: obj
})
})
},
/**
* 操作报名与签到
*/
handleOk() {
let data = this.data.activeData
//签到
if (data.activityStateCode == "4") {
if (data.enablePosition == 0) {
let params = {
trainingProjectId: this.options.id,
signTimeId: data.signTimeId,
signType: data.signType,
};
post(url.signInApi, params).then(() => {
wx.showToast({
title: '签到成功',
type: "success",
success: () => {
this.getActiveDetail()
}
})
})
} else {
let that = this
wx.scanCode({
// onlyFromCamera: true,
success(res) {
let obj = JSON.parse(res.result)
let params = {
trainingProjectId: obj.trainingProjectId,
signTimeId: obj.signTimeId,
signType: 1,
};
post(url.signCustomInApi, params).then(() => {
wx.showToast({
title: '签到成功',
type: "success",
success: () => {
that.getActiveDetail()
}
})
})
}
})
}
} else if(data.activityStateCode == "3"){
this.signUp()
}
},
// 报名
signUp() {
let params = {
id: this.options.id,
};
post(url.signUpApi, params).then(() => {
wx.showToast({
title: '报名成功',
type: "success",
success: () => {
this.getActiveDetail()
}
})
})
},
})
\ No newline at end of file
{
"usingComponents": {
"my-comment":"/pages/components/comment/index"
},
"navigationBarTitleText": "活动详情"
}
\ No newline at end of file
.activity-out {
width: 100%;
background-color: #f5f5f5;
min-height: 100vh;
.top-out {
width: 100%;
height: 170px;
padding: 20px;
background-image: url('https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=bgicon.png');
background-size: 100%;
background-repeat: no-repeat;
display: flex;
align-items: center;
box-sizing: border-box;
.tit {
color: #fff;
.line-hidden;
}
.tit-icon {
width: 80px;
background-color: #e5e6e8;
color: #a1a1a1;
text-align: center;
padding: 4px 0px;
border-radius: 4px;
margin-top: 25px;
}
.enroll {
color: #fff;
background-color: #53af5c;
}
.enrolled {
color: #fff;
background-color: #ffba19;
}
}
.line-hidden() {
margin: 0;
word-break: break-all;
text-overflow: ellipsis;
display: -webkit-box;
/** 对象作为伸缩盒子模型显示 **/
-webkit-box-orient: vertical;
/** 设置或检索伸缩盒对象的子元素的排列方式 **/
-webkit-line-clamp: 2;
/** 显示的行数 **/
overflow: hidden;
/** 隐藏超出的内容 **/
}
.mid-out {
transform: translateY(-12px);
width: 92%;
margin: 0 auto;
padding: 15px;
background-color: #fff;
box-sizing: border-box;
margin-bottom: 10px;
border-radius: 8px;
.image_class {
width: 86%;
margin: 12px auto;
height: auto;
}
.mid-item {
width: 100%;
display: flex;
color: #333;
margin-bottom: 5px;
font-size: 14px;
.item-font {
min-width: 72px;
color: #888;
margin-right: 10px;
}
}
.description {
text-indent: 2em;
}
}
.signup-button {
display: block;
width: 100%;
height: 45px;
line-height: 45px;
position: fixed;
bottom: 0;
font-size: 18px;
color: white;
text-align: center;
}
.btn1 {
background-color: #d23a29;
}
.btn2 {
background-color: #999999;
}
}
\ No newline at end of file
<view class="activity-out">
<!-- title -->
<view class="top-out">
<view style="width:40%;margin-right: 20px;">
<image src="{{activeData.logoImg}}" style="width: 100%;height: 105px;border-radius: 5px;" mode="aspectFill" />
</view>
<view style="width: 58%;">
<view class="tit">{{activeData.name}}</view>
<view class="tit-icon {{activeData.activityStateCode==2||activeData.activityStateCode==4||activeData.activityStateCode==5?'enrolled':'enroll'}}">{{activeData.activityStateCode==1?'待报名':activeData.activityStateCode==2?'已报名':activeData.activityStateCode==3?'报名':activeData.activityStateCode==4?'已报名':activeData.activityStateCode==5?'进行中':activeData.activityStateCode==6?'活动结束':activeData.activityStateCode==7?'未报名':'未签到'}}</view>
</view>
</view>
<!-- 规则 -->
<view class="mid-out">
<view class="mid-item">
<view class="item-font">活动时间:</view>
<view>{{activeData.startTime}} 至 {{activeData.endTime}}</view>
</view>
<view class="mid-item">
<view class="item-font">组织方:</view>
<view>{{activeData.organizer}}</view>
</view>
<view class="mid-item">
<view class="item-font">活动地点:</view>
<view>{{activeData.activityAddress}}</view>
</view>
<view class="mid-item">
<view class="item-font">活动名额:</view>
<view>{{activeData.enrollLimit}}人</view>
</view>
</view>
<!-- 介绍 -->
<view class="mid-out">
<view style="font-size: 20px;font-weight: bold;margin-bottom: 15px;">活动介绍</view>
<rich-text nodes="{{activeData.description}}" class="description" />
</view>
<view class="signup-button {{activeData.activityStateCode == 3 || activeData.activityStateCode == 4?'btn1':'btn2'}}" wx:if="{{!activeData.hasFinished}}" bind:tap="handleOk">{{activeData.activityStateName}}</view>
<!-- 评论 -->
<view wx:else>
<my-comment uploadImgStu="{{true}}" newsId="{{newsId}}" favoriteShow="{{fasle}}" bizType="{{2}}"></my-comment>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
Page({
data: {
activityList: [],
activityNavList: [],
activityTimeList: [],
current: 0,
},
onLoad() {
get(url.getactiveNavListApi, {
bizType: 1
}).then(res => {
if (res.data.activityType.length > 0) {
res.data.activityType.unshift({
activityType: "",
activityName: "所有日程",
});
}
this.setData({
activityNavList: res.data.activityType,
activityTimeList: res.data.theDay
})
})
let params = {
bizType: 1
}
this.getActivityList(params)
},
getActivityList(params) {
post(url.getActivityListApi, params).then(res => {
this.setData({
activityList: res.data.records
})
})
},
currentNav: function (e) {
let item = e.currentTarget.dataset.item;
let index = e.currentTarget.dataset.index;
this.setData({
current: index,
})
let params = {
activityType: item.activityType,
bizType: 1,
enablePay: 0,
pageNo: 1,
pageSize: 20
}
this.getActivityList(params)
},
myevent(e){
let params = {
bizType: 1,
pageNo: 1,
pageSize: 20,
now:e.detail
}
this.getActivityList(params)
},
handleTo(e){
let item = e.currentTarget.dataset.item;
wx.navigateTo({
url: '/pages/activity/activyDetail/index?id='+item.id,
})
}
});
\ No newline at end of file
{
"usingComponents": {
"calendar": "/pages/components/calendar/index"
},
"navigationBarTitleText": "活动服务"
}
\ No newline at end of file
<view class="activity-out">
<scroll-view scroll-x="true" enable-flex="true" class="scroll-view_H" scroll-left="{{ scrollLeft }}" scroll-with-animation="true">
<block wx:for="{{ activityNavList }}" wx:for-index="index" wx:key="index">
<view class="nav-item {{ current==index?'current-nav':'' }}" bindtap="currentNav" data-item="{{ item }}" data-index="{{ index }}">
{{ item.activityName }}
</view>
</block>
</scroll-view>
<calendar bind:myevent="myevent" activityTimeList="{{activityTimeList}}"/>
<view class="new-out">
<block wx:for="{{ activityList }}" wx:key="id" wx:for-index="index">
<view class="new-list" bindtap="handleTo" data-item="{{ item }}">
<image style="width: 36%;height:100px;" src="{{item.logoImg}}" mode="scaleToFill" />
<view class="new-item">
<view class="new-font">{{item.name}}</view>
<view style="color: #999;font-size: 12px;">
{{item.startTimeString}}-{{item.endTimeString}}
</view>
</view>
</view>
</block>
</view>
</view>
\ No newline at end of file
/* 一级滚动菜单 */
.scroll-view_H {
width: 100%;
display: flex;
background-color: #D23A29;
height: 40px;
line-height: 40px;
white-space: nowrap;
margin-bottom: 4px;
padding-bottom: 5px;
}
.nav-item {
height: 35px;
margin-left: 40rpx;
color: #fff;
}
/* 添加下边界 */
.current-nav {
border-bottom: 2px solid #fff;
}
/* 活动列表信息 */
.new-out {
width: 90%;
margin: 0 auto;
}
.new-list {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.new-font{
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
}
.new-item{
width: 60%;
height: 95px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
id: "",
bizType: "",
type: "",
list: {}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
id: options.id,
bizType: options.bizType
})
if (options.bizType == '1') {
this.setData({
type: '问卷'
})
wx.setNavigationBarTitle({
title: '工作任务'
});
} else {
this.setData({
type: '投票'
})
wx.setNavigationBarTitle({
title: '我要投票'
});
}
let params = {
researchId: options.id
}
post(url.getTaskDetailApi, params).then(res => {
for (const key in res.data) {
if (key == "startTime") {
res.data['startTime'] = moment(res.data['startTime']).format("YYYY年MM月DD日 HH:mm:ss")
}
}
this.setData({
list: res.data
})
})
},
handleTo() {
if (this.data.bizType == '2') {
wx.navigateTo({
url: '/pages/vote/index?id=' + this.data.id,
})
} else {
wx.navigateTo({
url: '/pages/questionnaire/index?id=' + this.data.id,
})
}
}
})
\ No newline at end of file
{
"usingComponents": {}
}
\ No newline at end of file
.describe-out {
padding: 20px 0;
width: 100%;
min-height: 100vh;
background: linear-gradient(0deg, #ff9286 0%, #d23a29),
linear-gradient(180deg, rgba(255, 255, 255, 0) 59%, #f5f5f5 100%),
linear-gradient(0deg, rgba(210, 58, 41, 0) 0%, #d23a29);
box-sizing: border-box;
.describe-top {
width: 92%;
margin: 0 auto;
margin-bottom: 20px;
.top-title {
width: 100%;
margin-bottom: 20px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 20px;
color: #fff;
font-weight: 500;
background: linear-gradient(90deg,
rgba(255, 151, 130, 0),
#ff9782 53%,
rgba(255, 151, 130, 0) 100%);
}
.top-img {
width: 100%;
height: 240px;
}
}
.describe-mid {
width: 92%;
margin: 0 auto;
background-color: #fff;
border-radius: 14px;
.mid-item {
padding: 10px;
.item-tit {
font-size: 20px;
font-weight: 600;
color: #353535;
margin-bottom: 5px;
}
.item-cont {
font-size: 16px;
font-weight: 500;
color: #333;
text-indent: 1em;
}
}
}
.describe-bot {
.describe-btn {
position: fixed;
bottom: 0;
width: 100%;
text-align: center;
padding: 10px 0;
background: linear-gradient(270deg, #eb6c53 0%, #d23a29);
border-radius: 5px;
color: #fff;
font-size: 18px;
}
}
}
\ No newline at end of file
<!-- 问卷,投票详情 -->
<view class="describe-out">
<view class="describe-top">
<view class="top-title">{{list.name}}</view>
<image src="{{list.image}}" class="top-img" mode="scaleToFill" />
</view>
<view class="describe-mid">
<!-- 主题 -->
<view class="mid-item">
<view class="item-tit">{{type}}主题</view>
<view class="item-cont" style="color: #333;">
{{list.content}}
</view>
</view>
<!-- 说明 -->
<view class="mid-item">
<view class="item-tit">{{type}}说明</view>
<view class="item-cont">{{list.remark}}</view>
</view>
<!-- 时间 -->
<view class="mid-item">
<view class="item-tit">{{type}}时间</view>
<view class="item-cont">
{{list.startTime}}
</view>
</view>
</view>
<view class="describe-bot">
<view class="describe-btn" bind:tap="handleTo">
立即{{type}}
</view>
</view>
</view>
\ No newline at end of file
const md5 = require('/miniprogram_npm/md5/index.js');
const {
sm2
} = require('/miniprogram_npm/sm-crypto/index.js');
const moment = require('/miniprogram_npm/moment/index.js');
const TOKEN_KEY = 'auth_token';
const { get, post } = require('../../utils/request');
import url from '../../utils/urlconfig'
Page({
data: {
btnstatus:'false',
newPassword: "",
repeatPassword: "",
},
onLoad() {
},
passwordBindinput: function (e) {
this.setData({
newPassword: e.detail.value
})
},
newPasswordBindinput: function (e) {
this.setData({
repeatPassword: e.detail.value
})
},
generateCharacter(n) {
var chars = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z']
var res = "";
for (var i = 0; i < n; i++) {
var id = Math.ceil(Math.random() * 35);
res += chars[id];
}
return res;
},
getCurrentDay() {
let date = ""
date = moment(new Date()).format("YYYYMMDD")
return date
},
changePasswordSubmit() {
const {
newPassword,
repeatPassword
} = this.data;
if (newPassword != repeatPassword) {
wx.showToast({
title: '两次密码输入不一致!',
icon: 'none',
duration: 1200
})
return;
}
let pattern = /(^.*(?=.{8,20})(?=.*\d)(?=.*[a-zA-Z])(?=.*[~!@#$%^&*()_+[\]{}|\;:'",./<>?]).*$)|(^.*(?=.{8,20})(?=.*\d)(?=.*[a-z])(?=.*\d)(?=.*[A-Z]).*$)|(^.*(?=.{8,20})(?=.*\d)(?=.*[a-z])(?=.*[~!@#$%^&*()_+[\]{}|\;:'",./<>?]).*$)|(^.*(?=.{8,20})(?=.*\d)(?=.*[A-Z])(?=.*[~!@#$%^&*()_+[\]{}|\;:'",./<>?]).*$)|(^.*(?=.{8,20})(?=.*[A-Z])(?=.*[a-z])(?=.*[~!@#$%^&*()_+[\]{}|\;:'",./<>?]).*$)/;
if (!pattern.test(newPassword)) {
wx.showToast({
title: '密码格式不正确',
icon: 'none',
duration: 1200
})
return;
}
const public_key = '047214fe3a249b75b6ba92ee494e0a8a68c0a19893a480b3c28bf06cd5b7d621243c7f6704caa3b43ade6be15de11cabd185611a9edfdcf1b11d7a2478c67b4c1c'
const private_key = '00a2bbe941a177ca9f200d1c4d37e8f0b43b9cd2ea662304a05c064c6416e74d49'
let salt = ""
let date = ""
let key = ""
let sign = ""
let password = ""
let confirmedPassword = ""
salt = this.generateCharacter(16)
console.log("validate-salt", salt)
date = this.getCurrentDay()
console.log("validate-date1111", date)
password = sm2.doEncrypt(newPassword + salt, public_key, 1);
confirmedPassword = sm2.doEncrypt(repeatPassword + salt, public_key, 1)
password = "04" + password
confirmedPassword = "04" + confirmedPassword
if (salt && date) {
key = salt + date
console.log("validate-key", key)
}
sign = "confirmPassword=" + confirmedPassword + "&password=" + password + "&salt=" + salt + "&key=" + key
console.log("validate-sign", md5(sign))
let parms = {
confirmPassword: confirmedPassword,
password,
salt: salt,
sign: md5(sign)
}
post(url.changPsdApi,parms).then(res => {
wx.showToast({
title: '修改密码成功!',
icon: 'success',
duration: 1500,
success:()=>{
this.goBack()
}
})
})
},
goBack() {
wx.reLaunch({
url: '/pages/login/index'
});
wx.setStorageSync(TOKEN_KEY, {
token: '',
expiry: ''
});
}
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "修改密码"
}
\ No newline at end of file
<view style="width: 96%;margin: 0 auto;padding-top: 40px;">
<view class="changePsd-out">
<view style="margin-right: 10px;letter-spacing: 0.5em;">新密码</view>
<input class="uni-input" bindinput="passwordBindinput" placeholder="请输入新密码" placeholder-style="color:#9E9E9E;" password />
</view>
<view class="changePsd-out">
<view style="margin-right: 18px;">确认密码</view>
<input class="uni-input" bindinput="newPasswordBindinput" placeholder="请再次输入新密码" placeholder-style="color:#9E9E9E;" password />
</view>
<view style="margin-bottom: 20px;">
<button class="confirm-btn" bindtap="changePasswordSubmit">修改密码</button>
</view>
<view class="password-instructor-container">
<view style="margin-bottom: 5px;">
<text>1) 密码控制只能输入字母、数字、特殊符号</text>
</view>
<view style="margin-bottom: 5px;">
<text>2) 长度 8-20 位,必须包括大小写字母、数字、特殊符号中的3种</text>
</view>
<view>
<text>3) 密码不能包含用户名信息</text>
</view>
</view>
</view>
\ No newline at end of file
/* pages/changePsd/index.wxss */
.changePsd-out{
display: flex;
margin-bottom: 20px;
}
.confirm-btn{
width: 100%;
background-color: red;
color: #fff;
}
.password-instructor-container{
font-size: 12px;
color: #222;
margin-bottom: 20px;
}
\ No newline at end of file
const moment = require('/miniprogram_npm/moment/index.js');
Component({
properties: {
activityTimeList: {
type: Array,
value: [],
observer: 'getCommentList'
},
},
data: {
year: 0,
month: 0,
calendarDays: [],
reminders: {},
showReminderModal: false,
showAddReminderModal: false,
selectedDate: '',
reminderInput: '',
},
methods: {
getCommentList() {
const currentDate = new Date();
this.setData({
year: currentDate.getFullYear(),
month: currentDate.getMonth() + 1,
});
this.generateCalendar(this.data.year, this.data.month);
},
// 生成指定年月的日历数据
generateCalendar(year, month) {
const firstDay = new Date(year, month - 1, 1);
const firstDayOfWeek = firstDay.getDay();
const lastDay = new Date(year, month, 0);
const daysInMonth = lastDay.getDate();
const days = [];
// 填充月初的空白
for (let i = 0; i < firstDayOfWeek; i++) {
days.push({
day: null,
date: null,
hasReminder: false
});
}
// 填充日期
for (let day = 1; day <= daysInMonth; day++) {
const date = `${year}-${month.toString().padStart(2, '0')}-${day.toString().padStart(2, '0')}`;
const hasReminder = this.properties.activityTimeList.some(e => e === date)
days.push({
day,
date,
hasReminder
});
}
this.setData({
calendarDays: days
});
},
// 切换到上一月
handlePrevMonth() {
let {
year,
month
} = this.data;
if (month === 1) {
year--;
month = 12;
} else {
month--;
}
this.setData({
year,
month
});
this.generateCalendar(year, month);
},
// 切换到下一月
handleNextMonth() {
let {
year,
month
} = this.data;
if (month === 12) {
year++;
month = 1;
} else {
month++;
}
this.setData({
year,
month
});
this.generateCalendar(year, month);
},
// 处理日期点击事件
handleDayClick(e) {
const date = e.currentTarget.dataset.date;
this.triggerEvent('myevent', date + ' 00:00:00')
// if (date) {
// this.setData({
// selectedDate: date
// });
// if (this.data.reminders[date] && this.data.reminders[date].length > 0) {
// this.setData({
// showReminderModal: true
// });
// } else {
// this.setData({
// showAddReminderModal: true
// });
// }
// }
},
// 关闭提醒详情模态框
closeReminderModal() {
this.setData({
showReminderModal: false
});
},
// 处理提醒输入
handleReminderInput(e) {
this.setData({
reminderInput: e.detail.value
});
},
// 添加提醒
addReminder() {
const {
selectedDate,
reminderInput,
reminders
} = this.data;
if (reminderInput) {
if (!reminders[selectedDate]) {
reminders[selectedDate] = [];
}
reminders[selectedDate].push(reminderInput);
this.setData({
reminders,
showAddReminderModal: false,
reminderInput: ''
});
this.generateCalendar(this.data.year, this.data.month);
}
},
// 取消添加提醒
cancelAddReminder() {
this.setData({
showAddReminderModal: false,
reminderInput: ''
});
}
}
});
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
// 定义党群风格的颜色变量
@primary-color: #eb4550;
@secondary-color: #ffd700;
// 日历容器样式
.calendar-container {
padding: 5px 20px 10px;
background-color: #f9f9f9;
// 日历头部样式
.calendar-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
// 上一月和下一月按钮样式
.prev-month,
.next-month {
width: 22%;
background-color: @primary-color;
color: white;
border: none;
padding: 5px 6px;
border-radius: 4px;
font-size: 16px;
cursor: pointer;
}
// 年月显示样式
.year-month {
width: 48%;
font-size: 18px;
font-weight: bold;
text-align: center;
color: @primary-color;
}
}
// 星期几显示样式
.calendar-weekdays {
display: flex;
justify-content: space-around;
margin-bottom: 5px;
color: @primary-color;
}
// 日历日期显示区域样式
.calendar-days {
display: grid;
grid-template-columns: repeat(7, 1fr);
gap: 10px;
// 有日期的格子样式
.calendar-day {
text-align: center;
padding:5px 6px;
background-color: white;
border-radius: 4px;
cursor: pointer;
position: relative;
&:hover {
background-color: @primary-color;
color: white;
}
// 提醒标记样式
.reminder-mark {
width: 8px;
margin: 0 auto;
height: 8px;
background-color: @primary-color;
border-radius: 50%;
}
}
// 空白格子样式
.calendar-day-empty {
visibility: hidden;
}
}
// 提醒详情模态框样式
.reminder-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
.reminder-modal-content {
background-color: white;
padding: 20px;
border-radius: 4px;
width: 80%;
.reminder-modal-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.reminder-modal-date {
color: #666;
margin-bottom: 10px;
}
.reminder-modal-reminders {
margin-bottom: 20px;
}
.reminder-modal-close {
background-color: @primary-color;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
}
}
// 添加提醒模态框样式
.add-reminder-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
.add-reminder-modal-content {
background-color: white;
padding: 20px;
border-radius: 4px;
width: 80%;
.add-reminder-modal-title {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.add-reminder-modal-date {
color: #666;
margin-bottom: 10px;
}
.add-reminder-modal-input {
border: 1px solid #ddd;
padding: 8px;
margin-bottom: 20px;
width: 100%;
}
.add-reminder-modal-add {
width: 33%;
background-color: @primary-color;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
margin-right: 10px;
}
.add-reminder-modal-cancel {
width: 33%;
background-color: #ccc;
color: white;
border: none;
padding: 8px 16px;
border-radius: 4px;
cursor: pointer;
}
}
}
}
\ No newline at end of file
<view class="calendar-container">
<!-- 日历头部,包含上一月、年月显示和下一月按钮 -->
<view class="calendar-header">
<button bindtap="handlePrevMonth" class="prev-month">上一月</button>
<view class="year-month">{{year}} 年 {{month}} 月</view>
<button bindtap="handleNextMonth" class="next-month">下一月</button>
</view>
<!-- 显示星期几 -->
<view class="calendar-weekdays">
<view>日</view>
<view>一</view>
<view>二</view>
<view>三</view>
<view>四</view>
<view>五</view>
<view>六</view>
</view>
<!-- 日历日期显示区域 -->
<view class="calendar-days">
<view wx:for="{{calendarDays}}" wx:key="index" class="{{item.day? 'calendar-day' : 'calendar-day-empty'}}" bindtap="handleDayClick" data-date="{{item.date}}">
{{item.day}}
<!-- 有提醒的日期显示提醒标记 -->
<view wx:if="{{item.hasReminder}}" class="reminder-mark"></view>
</view>
</view>
<!-- 提醒详情模态框 -->
<view wx:if="{{showReminderModal}}" class="reminder-modal">
<view class="reminder-modal-content">
<view class="reminder-modal-title">提醒详情</view>
<view class="reminder-modal-date">{{selectedDate}}</view>
<view class="reminder-modal-reminders">
<view wx:for="{{reminders[selectedDate]}}" wx:key="index">{{item}}</view>
</view>
<button bindtap="closeReminderModal" class="reminder-modal-close">关闭</button>
</view>
</view>
<!-- 添加提醒模态框 -->
<view wx:if="{{showAddReminderModal}}" class="add-reminder-modal">
<view class="add-reminder-modal-content">
<view class="add-reminder-modal-title">添加提醒</view>
<view class="add-reminder-modal-date">{{selectedDate}}</view>
<input placeholder="请输入提醒内容" bindinput="handleReminderInput" value="{{reminderInput}}" class="add-reminder-modal-input" />
<view style="display: flex;">
<button bindtap="addReminder" class="add-reminder-modal-add">添加</button>
<button bindtap="cancelAddReminder" class="add-reminder-modal-cancel">取消</button>
</view>
</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
Component({
properties: {
// 这里定义了newsId属性,属性值可以在组件使用时指定
newsId: {
type: String,
value: '',
observer: 'getCommentList'
},
favoriteState: {
type: String,
value: '',
observer: "changefavoriteStu"
},
uploadImgStu: {
type: Boolean,
value: false
},
favoriteShow: {
type: Boolean,
value: false
},
bizType: {
type: String,
value: 2
}
},
data: {
// 这里是一些组件内部数据
commentList: [],
imageList: [],
commentReplyList: [],
showModal: false,
showMoreStatu: false,
favoriteStu: false,
replyVal: "",
commentVal: "",
tpCommentId: "",
commentTotal: "",
uploadImgs:[]
},
lifetimes: {
attached: function () {
},
ready: function () {
},
detached: function () {
// 在组件实例被从页面节点树移除时执行
},
},
methods: {
// 这里是一个自定义方法
getCommentList: function () {
get(url.getCommentListApi, {
id: this.properties.newsId,
bizType: this.properties.bizType == 1 ? '2' : '',
pageNo: 1,
pageSize: 30,
}).then(res => {
let list = []
let resultList = []
res.data.records.forEach(item => {
if (item.tpCommentReplies.length > 0) {
resultList = list.concat(item.tpCommentReplies)
}
if(item.imageUrls){
item.imageUrls = JSON.parse(item.imageUrls);
}
});
this.setData({
commentList: res.data.records,
commentTotal: res.data.total,
commentReplyList: resultList
})
})
},
//点赞
laudClick: function (e) {
let item = e.currentTarget.dataset.item
let params = {
tpCommentId: item.id,
};
if (String(item.status) === "0") {
post(url.trainReviewGoodApi, params).then(res => {
wx.showToast({
title: '点赞成功',
icon: 'success',
duration: 2000
})
this.getCommentList()
})
} else {
post(url.trainReviewBadApi, params).then(res => {
wx.showToast({
title: '取消点赞',
icon: 'success',
duration: 2000
})
this.getCommentList()
})
}
},
//回复评论input
replyValBindinput: function (e) {
this.setData({
replyVal: e.detail.value
})
},
//评论input
commentValBindinput: function (e) {
this.setData({
commentVal: e.detail.value
})
},
// 展开更多回复
showMore: function () {
this.setData({
showMoreStatu: true
})
},
//回复
reviewDetail: function (e) {
this.setData({
showModal: true,
tpCommentId: e.currentTarget.dataset.item.id
})
},
//改变收藏状态
/**
* favoriteState 1:已收藏 0:未收藏
*/
changefavoriteStu() {
if (this.data.favoriteState == '1') {
this.setData({
favoriteStu: true
})
} else {
this.setData({
favoriteStu: false
})
}
},
// 收藏
setCollection() {
if (this.data.favoriteStu) {
get(url.setCancelFavoriteApi, {
studentCaseId: this.data.newsId
}).then(res => {
wx.showToast({
title: '取消收藏',
icon: 'success',
duration: 2000,
success: () => {
this.setData({
favoriteStu: false
})
}
})
})
} else {
get(url.setFavoriteApi, {
studentCaseId: this.data.newsId
}).then(res => {
wx.showToast({
title: '收藏成功',
icon: 'success',
duration: 2000,
success: () => {
this.setData({
favoriteStu: true
})
}
})
})
}
},
//相册调用
uploadImg() {
wx.chooseImage({
count: 4,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
// tempFilePath可以作为img标签的src属性显示图片
const tempFilePaths = res.tempFilePaths;
if (this.data.imageList.length > 3) {
wx.showToast({
title: '最多上传四张',
icon: 'error',
duration: 2000,
})
} else {
const TOKEN_KEY = 'auth_token';
const tokenData = wx.getStorageSync(TOKEN_KEY);
wx.uploadFile({
url: 'https://hqjddj.shanghaiairport.com/aliyun/api/upload/?companyCode=zhdj&siteCode=edu', // 服务器接口地址
filePath: tempFilePaths[0], // 单张图片路径
name: 'file', // 后台接收的字段名
header: {
'content-type': 'application/json', // 默认JSON格式
'Authorization': tokenData.token,
},
success: (res) => {
const data = JSON.parse(res.data); // 解析服务器响应
this.data.uploadImgs.push(data.data)
this.setData({
imageList: [...this.data.imageList, ...tempFilePaths]
});
},
});
}
}
})
},
//图片删除
deleteImage(e) {
const index = e.currentTarget.dataset.index;
const imageList = this.data.imageList.filter((_, i) => i !== index);
this.setData({
imageList
});
},
//图片预览
previewImage(e) {
const index = e.currentTarget.dataset.index;
const imageList = this.data.imageList;
wx.previewImage({
current: imageList[index], // 当前显示图片的http链接
urls: imageList // 需要预览的图片http链接列表
});
},
// 确认按钮事件
onConfirm() {
let params = {
content: this.data.replyVal,
tpCommentId: this.data.tpCommentId,
trainingProjectId: this.properties.newsId
}
post(url.setcommentRaplyApi, params).then(res => {
wx.showToast({
title: '回复评论成功',
icon: 'success',
duration: 2000
})
this.getCommentList();
this.hideModalFunc();
})
},
setComment: function () {
let params = {
content: this.data.commentVal,
bizType: this.properties.bizType == 2 ? "" : "2",
imageUrls: JSON.stringify(this.data.uploadImgs),
trainingProjectId: this.properties.newsId
}
post(url.setcommentApi, params).then(res => {
wx.showToast({
title: '评论成功',
icon: 'success',
duration: 2000,
success: () => {
this.setData({
commentVal: "",
imageList: []
})
this.getCommentList();
}
})
})
},
// 取消按钮事件
onCancel() {
// 处理取消逻辑
this.hideModalFunc();
},
// 显示模态框
showModalFunc() {
this.setData({
showModal: true
});
},
// 隐藏模态框
hideModalFunc() {
this.setData({
showModal: false
});
},
}
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
<view class="comment-out">
<view class="comment-num">当前评论({{commentTotal?commentTotal:'0'}})</view>
<view class="commit-top" wx:for="{{commentList}}" wx:key="id">
<view class="comment-item">
<view>
<image class="author-image" src="{{item.userAvatar?item.userAvatar:'./../../../static/common/my.png'}}" mode="" />
</view>
<view style="width: 100%;">
<view style="margin-bottom: 5px;font-weight: bold;">{{item.commentatorName}}</view>
<view>{{item.content}}</view>
<view style="display: flex;">
<view wx:for="{{item.imageUrls}}" data-index="{{index}}" wx:key="index">
<image src="{{item}}" mode="aspectFill" style="width: 70px;height: 70px;margin-right: 15px;" />
</view>
</view>
<view class="comment-footer">
<text class="comment-time">{{item.createTime}}</text>
<view class="handle-out">
<text>{{item.replys == "0" ? "0" : item.replys}}</text>
<view data-item="{{item}}" bindtap="reviewDetail">
<image src="./../../../static/common/train-comment.png" alt="" class="handle-icon" />
</view>
</view>
<view class="handle-out">
<text>{{item.thumbsUps == "0" ? "0" : item.thumbsUps}}</text>
<view data-item="{{item}}" bindtap="laudClick">
<image src="{{item.status == '1'?'./../../../static/common/alreadyzan.png':'./../../../static/common/zan.png'}}" alt="" class="handle-icon" />
</view>
</view>
</view>
<!-- 评论回复 -->
<view wx:if="{{item.tpCommentReplies.length>0}}" class="reply-out">
<view wx:for="{{commentReplyList}}" wx:key="id" style="margin-top: 15px;display: flex;" wx:if="{{showMoreStatu}}">
<image class="author-image author-reply" src="{{item.userAvatar?item.userAvatar:'./../../../static/common/my.png'}}" mode="" />
<view>
<view class="reply-user">{{item.createByFullName}}</view>
<view>{{item.content}}</view>
</view>
</view>
<view style="margin-top: 15px;display: flex;" wx:if="{{!showMoreStatu}}">
<image class="author-image author-reply" src="{{commentReplyList[0].userAvatar?commentReplyList[0].userAvatar:'./../../../static/common/my.png'}}" mode="" />
<view>
<view class="reply-user">{{commentReplyList[0].createByFullName}}</view>
<view>{{commentReplyList[0].content}}</view>
</view>
</view>
<view wx:if="{{!showMoreStatu&&commentReplyList.length>1}}" class="show-more-reply" bind:tap="showMore">展开更多回复</view>
</view>
</view>
</view>
</view>
<!-- 评论 -->
<view class="comment-input">
<view class="train-comment-contain">
<image class="cell-left-icon" src="./../../../static/common/comment-icon.jpg" alt="" />
<input type="text" value="{{commentVal}}" placeholder="欢迎发表你的观点" class="modal-input" bindinput="commentValBindinput" style="width: 70%;margin-right: 5px;" />
<view style="display: flex;">
<view bind:tap="setComment">
<image src="./../../../static/common/send-icon.png" class="cell-left-icon" style="margin-right: 5px;" alt="" />
</view>
<view wx:if="{{uploadImgStu}}" class="upload-img" bind:tap="uploadImg">
<image src="./../../../static/common/img-upload.png" class="cell-left-icon" style="margin-left: 5px;margin-right: 5px;" mode="" />
</view>
<view wx:if="{{favoriteShow}}" bind:tap="setCollection" >
<image src="{{favoriteStu?'./../../../static/common/alreadyCollection.png':'./../../../static/common/collection.png'}}" class="cell-left-icon" alt="" />
</view>
</view>
</view>
<view class="container" wx:if="{{uploadImgStu}}">
<view class="image-item" wx:for="{{imageList}}" wx:key="index">
<image src="{{item}}" mode="aspectFill" class="img-item" bindtap="previewImage" data-index="{{index}}"></image>
<image src="./../../../static/common/delect-img.png" mode="" class="delete-btn" bindtap="deleteImage" data-index="{{index}}" />
</view>
</view>
</view>
</view>
<!-- 自定义模态框 WXML -->
<view class="custom-modal" wx:if="{{showModal}}">
<!-- 遮罩层 -->
<view class="modal-mask" bindtap="hideModalFunc"></view>
<!-- 模态内容 -->
<view class="modal-content">
<view class="modal-buttons">
<view class="modal-button cancel" bindtap="onCancel">取消</view>
<text class="modal-title">回复</text>
<view class="modal-button confirm" bindtap="onConfirm">确认</view>
</view>
<input type="text" placeholder="回复 {{name}}" class="modal-input" bindinput="replyValBindinput" />
</view>
</view>
\ No newline at end of file
.comment-out {
width: 94%;
margin: 0 auto;
padding: 10px;
background-color: #fff;
box-sizing: border-box;
}
.comment-num {
margin-bottom: 20px;
}
.commit-top{
padding-bottom: 40px;
}
.comment-item {
display: flex;
font-size: 14px;
margin-bottom: 10px;
}
.author-image {
width: 45px;
height: 45px;
border-radius: 50%;
margin-right: 10px;
}
.author-reply {
width: 30px;
height: 30px;
}
.comment-footer {
width: 100%;
display: flex;
justify-content: space-between;
margin-top: 20px;
}
.comment-time {
font-size: 12px;
}
.handle-out {
display: flex;
font-size: 14px;
}
.handle-icon {
width: 18px;
height: 18px;
margin-left: 5px;
}
.reply-out {
font-size: 12px;
padding: 10px;
}
.reply-user {
font-size: 13px;
margin-bottom: 5px;
}
.show-more-reply {
color: #4a90e2;
margin-top: 8px;
}
.comment-input {
position: fixed;
bottom: 0;
left: 0;
width: 100%;
}
.train-comment-contain {
background-color: white;
padding: 5px 10px;
display: flex;
justify-content: space-between;
align-items: center;
width: 100%;
z-index: 100001;
box-sizing: border-box;
}
.cell-left-icon {
width: 24px;
height: 24px;
}
.comment-slider {
background: #f4f4f4;
border-radius: 23px;
width: 90%;
height: 60px;
display: flex;
align-items: center;
padding-left: 0.2rem;
font-size: 17pt;
color: #959595;
letter-spacing: 0.1px;
float: right;
}
/* 上传图片 */
.container{
background-color: #fff;
width: 100%;
padding-bottom: 20px;
margin-left: 20px;
}
.container{
display: flex;
}
.image-item{
width: 60px;
height: 60px;
position: relative;
margin-right: 10px;
margin-top: 15px;
box-sizing: border-box;
}
.img-item{
width: 60px;
height: 60px;
border-radius: 10px;
box-shadow:
5px 5px 5px #00000014,
5px -5px 5px #00000014,
-5px 5px 5px #00000014,
-5px -5px 5px #00000014;
}
.delete-btn{
width: 18px;
height: 18px;
position: absolute;
top: -5px;
right: -8px;
font-size: 10px;
}
/* 遮罩层样式 */
.modal-mask {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
z-index: 1;
}
/* 模态内容样式 */
.modal-content {
background-color: #fff;
padding: 10px 4px 26px 4px;
border-radius: 10px 10px 0px 0px;
width: 100%;
position: fixed;
bottom: 0;
left: 0;
z-index: 2;
box-sizing: border-box;
}
/* 自定义模态框 WXSS */
.custom-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
justify-content: center;
align-items: center;
}
.modal-title {
font-size: 16px;
font-weight: bold;
margin-bottom: 10px;
}
.modal-message {
font-size: 14px;
margin-bottom: 20px;
}
.modal-buttons {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 10px;
}
.modal-button {
padding: 4px 10px;
border-radius: 5px;
text-align: center;
}
.cancel {
color: #000;
}
.confirm {
color: rgb(240, 38, 38);
}
.modal-input {
width: 90%;
min-height: 35px;
margin: 0 auto;
background-color: #f4f4f4;
border-radius: 20px;
padding-left: 5px;
}
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
Component({
properties: {
// 这里定义了newsId属性,属性值可以在组件使用时指定
questionData: {
type: Object,
value: {},
},
answerQuestionData: {
type: Object,
value: {},
observer: 'getAnswer'
},
},
data: {
// 这里是一些组件内部数据
essayVal:"",
fileName:""
},
lifetimes: {
attached: function () {
},
ready: function () {
this.setData({
fileName:this.data.questionData?.contentAppendixUrl?.split('prefix=')[1],
})
},
},
methods: {
getAnswer(e){
console.log('箭头',e)
this.setData({
essayVal: e?.questionItems[0]?.content
})
},
triggerCustomEvent: function(newValue) {
this.setData({
essayVal: newValue
});
},
bindlinechange(e){
this.setData({
essayVal:e.detail.value
})
},
downLoad(){
wx.downloadFile({
url: this.data.questionData.contentAppendixUrl,
success: function (res) {
const filePath = res.tempFilePath;
//预览
wx.openDocument({
filePath: filePath,
success: function (res) {
console.log('打开文档成功')
}
})
// 保存文件
// wx.saveFile({
// tempFilePath: filePath,
// success: function (res) {
// const savedFilePath = res.savedFilePath;
// wx.showToast({
// title: '文件已保存',
// icon: 'success'
// });
// },
// fail: function (err) {
// console.error('保存文件失败', err);
// }
// });
},
fail: function (err) {
console.error('下载文件失败', err);
}
});
}
}
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
.inp{
width: 100%;
height: 80px;
border: 1px solid #999;
border-radius: 4px;
padding-left: 8px;
padding-top: 8px;
box-sizing: border-box;
font-size: 14px;
}
.file-name {
color: #1989fa;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 20px;
}
\ No newline at end of file
<!-- 问答题 -->
<view class="container">
<view style="margin-bottom: 20px;font-size: 14px;text-indent: 2em;">{{questionData.remark}}</view>
<view style="background-color: rgb(248, 248, 248);"></view>
<view style="margin-bottom: 20px;font-size: 14px;">
<text style="color: #67512c;">问答题 </text>
{{questionData.content}}
</view>
<view class="file-name" bind:tap="downLoad" wx:if="{{fileName}}">
{{fileName}}
</view>
<view>
<textarea class="inp" type="text" value="{{essayVal}}" placeholder="请输入你的回答" bindinput="bindlinechange" />
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
Component({
properties: {
// 这里定义了newsId属性,属性值可以在组件使用时指定
questionData: {
type: Object,
value: {},
// observer: 'getCommentList'
},
},
data: {
// 这里是一些组件内部数据
multipleVal:[],
fileName:""
},
lifetimes: {
attached: function () {
},
ready: function () {
this.setData({
fileName:this.data.questionData.contentAppendixUrl?.split('prefix=')[1]
})
},
detached: function () {
// 在组件实例被从页面节点树移除时执行
},
},
methods: {
// 这里是一个自定义方法
checkboxChange(e){
this.setData({
multipleVal:e.detail.value
})
},
downLoad(){
wx.downloadFile({
url: this.data.questionData.contentAppendixUrl,
success: function (res) {
const filePath = res.tempFilePath;
//预览
wx.openDocument({
filePath: filePath,
success: function (res) {
console.log('打开文档成功')
}
})
// 保存文件
// wx.saveFile({
// tempFilePath: filePath,
// success: function (res) {
// const savedFilePath = res.savedFilePath;
// wx.showToast({
// title: '文件已保存',
// icon: 'success'
// });
// },
// fail: function (err) {
// console.error('保存文件失败', err);
// }
// });
},
fail: function (err) {
console.error('下载文件失败', err);
}
});
}
}
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
.weui-cell {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.file-name {
color: #1989fa;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 20px;
}
\ No newline at end of file
<!-- 多选题 -->
<view class="container">
<view style="margin-bottom: 20px;font-size: 15px;text-indent: 2em;">{{questionData.remark}}</view>
<view style="margin-bottom: 20px;font-size: 15px;">
<text style="color: #67512c;">多选题 </text>
{{questionData.content}}
</view>
<view class="file-name" bind:tap="downLoad" wx:if="{{fileName}}">
{{fileName}}
</view>
<checkbox-group bindchange="checkboxChange">
<label class="weui-cell weui-check__label" wx:for="{{questionData.options}}" wx:key="id">
<view class="weui-cell__hd">
<checkbox value="{{item.id}}" />
</view>
<view class="weui-cell__bd">{{item.content}}</view>
</label>
</checkbox-group>
</view>
\ No newline at end of file
Component({
properties: {
questionData: {
type: Object,
value: {},
// observer: 'getCommentList'
},
},
data: {
// 这里是一些组件内部数据
radioVal: '',
checkBoxVal: [],
InputVal: '',
examAnswered: false
},
lifetimes: {
attached: function () {
},
ready: function () {
},
},
methods: {
radioChange(e) {
this.setData({
radioVal: e.detail.value
})
},
checkboxChange(e) {
this.setData({
checkBoxVal: e.detail.value
})
},
bindInputChange(e) {
this.setData({
InputVal: e.detail.value
})
},
}
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
.question-items{
width: 100%;
background-color: #fff;
padding: 25px;
box-sizing: border-box;
.weui-cell{
display: flex;
margin-top: 15px;
}
}
\ No newline at end of file
<view class="question-items">
<view>
<text>{{questionData.index+1}}.</text>
<text>{{questionData.type==1?'单选题':questionData.type==2?'多选题':questionData.type==3?'判断题':'问答题'}}</text>
<text>({{questionData.score}}分)</text>
</view>
<view style="margin-top: 15px;margin-left: 15px;">
<view>{{questionData.stem}}</view>
<view wx:if="{{questionData.type == 1 || questionData.type == 3}}">
<radio-group bindchange="radioChange">
<label class="weui-cell" wx:for="{{questionData.questionOptions}}" wx:key="content">
<view class="weui-cell__hd">
<radio value="{{item.optionId}}" checked="{{item.answer==1}}"/>
</view>
<view class="weui-cell__bd">{{item.content}}</view>
</label>
</radio-group>
</view>
<view wx:if="{{questionData.type == 2}}">
<checkbox-group bindchange="checkboxChange">
<label class="weui-cell" wx:for="{{questionData.questionOptions}}" wx:key="content">
<view class="weui-cell__hd">
<checkbox value="{{item.optionId}}" checked="{{item.answer==1}}"/>
</view>
<view class="weui-cell__bd">{{item.content}}</view>
</label>
</checkbox-group>
</view>
<view wx:if="{{questionData.type == 4}}">
<textarea bindinput="bindInputChange" auto-height placeholder="请输入你的回答" />
</view>
</view>
</view>
\ No newline at end of file
Component({
properties: {
questionData: {
type: Object,
value: {},
// observer: 'getCommentList'
},
},
data: {
// 这里是一些组件内部数据
scoringVal:"",
fileName:""
},
lifetimes: {
attached: function () {
},
ready: function () {
this.setData({
fileName:this.data.questionData.contentAppendixUrl?.split('prefix=')[1]
})
},
},
methods: {
sliderChange(e){
this.setData({
scoringVal:e.detail.value
})
},
// 这里是一个自定义方法
downLoad(){
wx.downloadFile({
url: this.data.questionData.contentAppendixUrl,
success: function (res) {
const filePath = res.tempFilePath;
//预览
wx.openDocument({
filePath: filePath,
success: function (res) {
console.log('打开文档成功')
}
})
// 保存文件
// wx.saveFile({
// tempFilePath: filePath,
// success: function (res) {
// const savedFilePath = res.savedFilePath;
// wx.showToast({
// title: '文件已保存',
// icon: 'success'
// });
// },
// fail: function (err) {
// console.error('保存文件失败', err);
// }
// });
},
fail: function (err) {
console.error('下载文件失败', err);
}
});
}
}
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
.inp{
width: 100%;
height: 30px;
border: 1px solid #999;
border-radius: 4px;
padding-left: 8px;
box-sizing: border-box;
font-size: 14px;
}
.file-name {
color: #1989fa;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 20px;
}
\ No newline at end of file
<!-- 打分题 -->
<view class="container">
<view style="margin-bottom: 20px;font-size: 14px;text-indent: 2em;">{{questionData.remark}}</view>
<view style="margin-bottom: 20px;font-size: 14px;">
<text style="color: #67512c;">打分 </text>
{{questionData.content}}
</view>
<view class="file-name" bind:tap="downLoad" wx:if="{{fileName}}">
{{fileName}}
</view>
<view>
<slider bindchange="sliderChange" min="0" max="10" show-value/>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
Component({
properties: {
// 这里定义了newsId属性,属性值可以在组件使用时指定
questionData: {
type: Object,
value: {},
},
answerQuestionData: {
type: Object,
value: {},
observer: 'getAnswer'
},
},
data: {
// 这里是一些组件内部数据
singleVal: "",
fileName: ""
},
lifetimes: {
attached: function () {
},
ready: function () {
this.setData({
fileName: this.data.questionData.contentAppendixUrl?.split('prefix=')[1]
})
},
detached: function () {
// 在组件实例被从页面节点树移除时执行
},
},
methods: {
getAnswer(e){
console.log('箭头',e)
this.setData({
singleVal: e?.questionItems[0].optionId
})
},
radioChange(e) {
console.log('单选题',e.detail.value)
this.setData({
singleVal: e.detail.value
})
},
downLoad() {
wx.downloadFile({
url: this.data.questionData.contentAppendixUrl,
success: function (res) {
const filePath = res.tempFilePath;
//预览
wx.openDocument({
filePath: filePath,
success: function (res) {
console.log('打开文档成功')
}
})
// 保存文件
// wx.saveFile({
// tempFilePath: filePath,
// success: function (res) {
// const savedFilePath = res.savedFilePath;
// wx.showToast({
// title: '文件已保存',
// icon: 'success'
// });
// },
// fail: function (err) {
// console.error('保存文件失败', err);
// }
// });
},
fail: function (err) {
console.error('下载文件失败', err);
}
});
}
}
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
.weui-cell {
display: flex;
align-items: center;
margin-bottom: 20px;
}
.file-name {
color: #1989fa;
font-size: 14px;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 20px;
}
\ No newline at end of file
<!-- 单选题 -->
<view class="container">
<view style="margin-bottom: 20px;font-size: 15px;text-indent: 2em;">{{questionData.remark}}</view>
<view style="margin-bottom: 20px;font-size: 15px;">
<text style="color: #67512c;">单选题 </text>
{{questionData.content}}
</view>
<view class="file-name" bind:tap="downLoad" wx:if="{{fileName}}">
{{fileName}}
</view>
<radio-group bindchange="radioChange">
<label class="weui-cell" wx:for="{{questionData.options}}" wx:key="id">
<view class="weui-cell__hd">
<radio value="{{item.id}}" checked="{{item.id==singleVal}}"/>
</view>
<view class="weui-cell__bd">{{item.content}}</view>
</label>
</radio-group>
</view>
\ No newline at end of file
Component({
properties: {
},
data: {
// 这里是一些组件内部数据
imageList: [],
previewImages: [],
uploadFile: []
},
methods: {
chooseMedia() {
wx.chooseMedia({
mediaType: ['image', 'video'],
sourceType: ['album', 'camera'],
maxDuration: 30,
camera: 'back',
success: (res) => {
console.log(res)
this.uploadImg(res.tempFiles[0].tempFilePath)
//预览数据
let previewItems = [];
let previewItem = {
url: res.tempFiles[0].tempFilePath,
type: res.tempFiles[0].fileType,
}
previewItems.push(previewItem)
let imgs = [];
imgs.push(res.tempFiles[0].tempFilePath)
this.setData({
imageList: [...this.data.imageList, ...imgs],
previewImages: [...this.data.previewImages, ...previewItems],
});
}
});
},
//图片上传
uploadImg(url) {
const TOKEN_KEY = 'auth_token';
const tokenData = wx.getStorageSync(TOKEN_KEY);
let imgs = []
wx.uploadFile({
url: 'https://hqjddj.shanghaiairport.com/aliyun/api/upload/?companyCode=zhdj&siteCode=edu', // 服务器接口地址
filePath: url, // 单张图片路径
name: 'file', // 后台接收的字段名
header: {
'content-type': 'application/json', // 默认JSON格式
'Authorization': tokenData.token,
},
success: (res) => {
const data = JSON.parse(res.data); // 解析服务器响应
this.data.uploadFile.push(data.data)
},
fail(err) {
console.error('上传失败', err);
}
});
},
//图片删除
deleteImage(e) {
const index = e.currentTarget.dataset.index;
const imageList = this.data.imageList.filter((_, i) => i !== index);
this.setData({
imageList
});
},
//图片预览1
previewImage(e) {
const index = e.currentTarget.dataset.index;
wx.previewMedia({
sources: this.data.previewImages,
current: index
});
},
},
})
\ No newline at end of file
{
"component": true
}
\ No newline at end of file
.img-container {
background-color: #fff;
width: 100%;
padding-bottom: 20px;
display: flex;
flex-wrap: wrap;
justify-content: flex-start;
.image-item {
width: 70px;
height: 70px;
position: relative;
margin-right: 20px;
margin-top: 15px;
box-sizing: border-box;
.img-item {
width: 70px;
height: 70px;
border-radius: 10px;
box-shadow:
5px 5px 5px #00000014,
5px -5px 5px #00000014,
-5px 5px 5px #00000014,
-5px -5px 5px #00000014;
}
.delete-btn {
width: 18px;
height: 18px;
position: absolute;
top: -5px;
right: -8px;
font-size: 10px;
}
}
}
.upload-img{
background-color: #f5f5f5;
width: 70px;
height: 70px;
border-radius: 5px;
display: flex;
justify-content: center;
align-items: center;
flex-direction: column;
.upload-icon{
width: 18px;
height: 18px;
margin-top: 8px;
}
.upload-font{
width: 86%;
margin: 5px auto;
font-size: 10px;
color: #999;
text-align: center;
}
}
\ No newline at end of file
<view>
<view class="img-container">
<view class="image-item" wx:for="{{imageList}}" wx:key="index">
<image src="{{item}}" mode="aspectFill" class="img-item" bindtap="previewImage" data-index="{{index}}"></image>
<image src="/static/common/delect-img.png" mode="" class="delete-btn" bindtap="deleteImage" data-index="{{index}}" />
</view>
</view>
<view class="upload-img" bind:tap="chooseMedia">
<image class="upload-icon" src="/static/upload-img.png" mode="aspectFill" />
<view class="upload-font">点击上传图片或视频</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
Page({
data: {
activeId: null,
activeTwoId: null,
activeThreeId: null,
typeOne: null,
typeTwo: null,
typeThree: null,
mapList: [],
mapTwoList: [],
mapThreeList: [],
detailStu: true,
videoVisible: false,
authValue: "",
delValue: "",
titleValue: "",
contentValue: "",
previewVisible: false,
previewImage: "",
selectList: [],
selectIndex: 0
},
onLoad() {
get(url.getContributeListApi, {
id: 2
}).then(response => {
this.setData({
mapList: response.data
});
});
post(url.getSelectListApi, {}).then(response => {
this.setData({
selectList: response.data.records
});
});
},
handleClick(e) {
const {
index,
item
} = e.currentTarget.dataset;
get(url.getContributeListApi, {
id: item.id
}).then(response => {
this.setData({
mapTwoList: response.data,
mapThreeList: []
});
});
if (this.data.activeId !== index) {
this.setData({
activeId: index,
activeTwoId: null,
typeOne: item.value,
typeTwo: null,
activeThreeId: null,
typeThree: null
});
}
},
handleTwoClick(e) {
const {
index,
item
} = e.currentTarget.dataset;
get(url.getContributeListApi, {
id: item.id
}).then(response => {
this.setData({
mapThreeList: response.data,
});
});
if (this.data.activeTwoId !== index) {
this.setData({
activeTwoId: index,
activeThreeId: null,
typeTwo: item.value,
typeThree: null
});
}
},
handleThreeClick(e) {
const {
index,
item
} = e.currentTarget.dataset;
if (this.data.activeThreeId !== index) {
this.setData({
activeThreeId: index,
typeThree: item.value
});
}
},
handleTo() {
const {
typeOne,
typeTwo,
typeThree
} = this.data;
if (!typeOne) {
wx.showToast({
title: '请选择投稿类型',
icon: 'none'
});
} else {
this.setData({
detailStu:false
})
}
},
onTitleChange(e) {
this.setData({
titleValue: e.detail.value
});
},
onContentChange(e) {
this.setData({
contentValue: e.detail.value
});
},
onAuthChange(e) {
this.setData({
authValue: e.detail.value
});
},
onSelectChange(e) {
this.setData({
selectIndex: e.detail.value
});
},
showVideoModal() {
this.setData({
videoVisible: true
});
},
closeVideoModal() {
this.setData({
videoVisible: false
});
},
handleSumbit() {
const uploadData = this.selectComponent('#upload')?.data;
let params = {
fileName: this.data.titleValue,
typeOne: this.data.typeOne,
typeTwo: this.data.typeTwo,
typeThree: this.data.typeThree,
author: this.data.authValue,
content: this.data.contentValue,
ossUrl: JSON.stringify(uploadData.uploadFile),
deptName: this.data.selectList[this.data.selectIndex].name
};
if (!this.data.titleValue) {
wx.showToast({
title: '请输入标题',
icon: 'none'
});
return;
}
if (!this.data.contentValue) {
wx.showToast({
title: '请输入内容',
icon: 'none'
});
return;
}
if (!this.data.authValue) {
wx.showToast({
title: '请输入作者',
icon: 'none'
});
return;
}
if (!this.data.selectList[this.data.selectIndex]) {
wx.showToast({
title: '请选择支部和部室',
icon: 'none'
});
return;
}
post(url.commitContributeApi,params).then(res=>{
if (res.code == 1000) {
wx.showToast({
title: '提交成功',
icon: 'success',
success:()=>{
this.setData({
detailStu:true,
})
}
});
}
})
}
});
\ No newline at end of file
{
"usingComponents": {
"upload-media":"/pages/components/uploadMedia/index"
},
"navigationBarTitleText": "我要投稿"
}
\ No newline at end of file
.mycontribute-out {
background-color: #f5f5f5;
min-height: 100vh;
.mycontribute-tit {
font-size: 20px;
font-weight: bold;
padding: 20px 10px;
margin-left: 10px;
color: #333;
}
.mycontribute-box {
background-color: #fff;
width: 92%;
margin: 0 auto;
padding: 20px 10px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.item-box {
width: 48%;
margin-bottom: 15px;
height: 50px;
line-height: 50px;
background-color: #f7f7f7;
text-align: center;
font-size: 16px;
color: #454343;
}
.item-box-active {
width: 48%;
margin-bottom: 15px;
height: 50px;
line-height: 50px;
background: rgba(253, 63, 52, 0.05);
border: 1px solid #f3ab9f;
border-radius: 4px;
text-align: center;
font-size: 16px;
color: #454343;
}
span {
width: 100%;
color: #e6624a;
}
}
.mycontribute-child-box {
background-color: #fff;
width: 92%;
margin: 0 auto;
padding: 40px 25px;
}
.mycontribute-btn {
width: 92%;
margin: 0 auto;
text-align: center;
padding: 12px 0;
background: linear-gradient(270deg, #eb6c53 0%, #d23a29);
border-radius: 5px;
color: #fff;
font-size: 18px;
}
}
//投稿详情
.contribute-detail-out {
width: 92%;
margin: 20px auto;
padding-bottom: 15px;
.contribute-detail-box {
padding: 20px 15px;
background-color: #fff;
margin-bottom: 15px;
.top-tit {
font-size: 20px;
font-weight: bold;
color: #000;
margin-bottom: 15px;
.red-star {
color: red;
font-size: 18px;
}
}
.user-tit {
color: #999999;
font-size: 16px;
}
.userinfo-box {
margin-top: 15px;
display: flex;
justify-content: space-between;
align-items: center;
.userinfo-name {
color: #666666;
font-size: 20px;
}
}
.contribute-select {
width: 50%;
border: 0 !important;
font-size: 32px !important;
height: 60px !important;
line-height: 60px !important;
}
}
.contribute-detail-btn {
display: flex;
justify-content: space-between;
.perview-btn {
width: 48%;
text-align: center;
color: #666;
font-size: 18px;
padding: 10px 0;
border: 1px solid #666;
border-radius: 4px;
}
.sumbit-btn {
width: 48%;
text-align: center;
color: #fff;
font-size: 18px;
padding: 10px 0;
border-radius: 4px;
background: linear-gradient(270deg, #eb6c53 0%, #d23a29);
}
}
}
.preview-modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, 0.5);
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.preview-out {
width: 85%;
background-color: white;
padding: 20px;
border-radius: 10px;
box-sizing: border-box;
.preview-top {
width: 100%;
.preview-tit {
font-size: 20px;
color: #000;
font-weight: bold;
}
.preview-user {
display: flex;
.user-item {
color: #999;
font-size: 18px;
margin-right: 15px;
}
}
}
.preview-mid {
.preview-imgs {
img {
width: 100%;
// height: 180px;
}
}
.perview-con {
font-size: 36px;
color: #000;
}
}
}
}
\ No newline at end of file
<view class="mycontribute-out">
<view wx:if="{{detailStu}}">
<view class="mycontribute-tit">请选择投稿类型</view>
<!-- 一级分类列表 -->
<view class="mycontribute-box">
<block wx:for="{{mapList}}" wx:key="id">
<view class="{{activeId === index? 'item-box-active' : 'item-box'}}" bindtap="handleClick" data-index="{{index}}" data-item="{{item}}">
{{item.cnName}}
</view>
</block>
</view>
<!-- 二级分类列表 -->
<block wx:if="{{mapTwoList.length > 0}}">
<view class="mycontribute-box">
<block wx:for="{{mapTwoList}}" wx:key="id">
<view class="{{activeTwoId === index? 'item-box-active' : 'item-box'}}" bindtap="handleTwoClick" data-index="{{index}}" data-item="{{item}}">
{{item.cnName}}
</view>
</block>
</view>
</block>
<!-- 三级分类列表 -->
<block wx:if="{{mapThreeList.length > 0}}">
<view class="mycontribute-box">
<block wx:for="{{mapThreeList}}" wx:key="id">
<view class="{{activeThreeId === index? 'item-box-active' : 'item-box'}}" bindtap="handleThreeClick" data-index="{{index}}" data-item="{{item}}">
{{item.cnName}}
</view>
</block>
</view>
</block>
<view class="mycontribute-btn" bindtap="handleTo">写稿</view>
</view>
<view wx:else class="contribute-detail-out">
<!-- 标题输入框 -->
<view class="contribute-detail-box">
<view class="top-tit">
标题 <text class="red-star">*</text>
</view>
<input placeholder="标题需15字以内" value="{{titleValue}}" bindinput="onTitleChange" maxlength="15" style="height: 60px; line-height: 60px;" />
</view>
<!-- 正文输入框 -->
<view class="contribute-detail-box">
<view class="top-tit">
正文<text class="red-star">*</text>
</view>
<textarea value="{{contentValue}}" bindinput="onContentChange" placeholder="请输入正文" rows="8" />
</view>
<!-- 图片或视频上传 -->
<view class="contribute-detail-box">
<view class="top-tit">图片或视频上传</view>
<upload-media id="upload"></upload-media>
</view>
<!-- 用户信息 -->
<view class="contribute-detail-box">
<view class="user-tit">以下为公开信息,将会在稿件中显示</view>
<view class="userinfo-box">
<view class="userinfo-name">
作者<text style="color: red;">*</text>
</view>
<input value="{{authValue}}" bindinput="onAuthChange" placeholder="请输入" style="width: 50%; height: 60px; line-height: 60px;" />
</view>
<view class="userinfo-box">
<view class="userinfo-name">
支部和科室<text style="color: red;">*</text>
</view>
<picker mode="selector" range="{{selectList}}" range-key="name" bindchange="onSelectChange" value="{{selectIndex}}">
<view class="picker">
{{selectList[selectIndex]? selectList[selectIndex].name : '请选择'}}
</view>
</picker>
</view>
</view>
<!-- 操作按钮 -->
<view class="contribute-detail-btn">
<view class="perview-btn" bindtap="showVideoModal">
预览
</view>
<view class="sumbit-btn" bindtap="handleSumbit">
提交
</view>
</view>
<!-- 预览模态框 -->
<view class="preview-modal" hidden="{{!videoVisible}}">
<view class="preview-out">
<view class="preview-top">
<view class="preview-tit">{{titleValue}}</view>
</view>
<view class="preview-mid">
<view class="perview-con">{{contentValue}}</view>
<view class="preview-imgs">
<image src="{{item.fileUrl}}" mode="aspectFit" wx:for="{{fileList}}" wx:key="*this" />
</view>
</view>
<view class="preview-user">
<view class="user-item">{{authValue}}</view>
<view class="user-item">{{selectList[selectIndex]? selectList[selectIndex].name : ''}}</view>
</view>
</view>
<button bindtap="closeVideoModal">关闭</button>
</view>
</view>
</view>
\ No newline at end of file
Page({
data: {
},
onLoad() {
},
});
\ No newline at end of file
{
"usingComponents": {}
}
\ No newline at end of file
<!--pages/h5Link/index.wxml-->
<view class="webview-container">
<web-view binderror='binderror' src="https://hqjddj.shanghaiairport.com/#/zhdj/edu/login"/>
</view>
\ No newline at end of file
/* pages/h5Link/index.wxss */
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
swiperHeight: 0,
navHeight: 0,
customTop: 0,
customHeight: 0,
homeBannerList: [],
newsList: [],
navLists: []
},
onLoad() {
let custom = wx.getMenuButtonBoundingClientRect(); // 小程序右上角胶囊信息
let system = wx.getWindowInfo(); // 获取设备信息的距离
get(url.homeItemApi, {
terminalName: 'WECHAT'
}).then(res => {
res.data.newsList.map((item) => {
item.releaseTime = moment(item.releaseTime).format("YYYY-MM-DD")
})
res.data.navigateList.map((item) => {
if (item.type == 'news') {
item['path'] = '/pages/NewsMessage/index?id=' + item.relationId + `&relationName=` + item.relationFuncName
}
if (item.type == 'train') {
item['path'] = '/pages/activity/index'
}
if (item.type == 'mysurvey') {
item['path'] = '/pages/workTask/index?type=1'
}
if ( item.type == 'survey') {
item['path'] = '/pages/workTask/index?type=2'
}
if ( item.type == 'mycontribute') {
item['path'] = '/pages/contribute/index'
}
if ( item.type == 'myexam') {
item['path'] = '/pages/trainingAndTest/index?id=' + item.relationId
}
})
this.setData({
homeBannerList: res.data.imageList,
newsList: res.data.newsList,
navLists: res.data.navigateList,
navHeight: system.statusBarHeight + 44, // 导航栏的高度
customTop: custom.top, // 胶囊按钮与顶部的距离
customHeight: custom.height, // 胶囊按钮与右侧
swiperHeight: system.statusBarHeight + 44
})
})
},
handleTo(e){
let item = e.currentTarget.dataset.item
wx.navigateTo({
url: '/pages/NewsMessage/news/index?id='+item.id,
})
},
toSearch(){
wx.navigateTo({
url: '/pages/searchInfo/index',
})
},
});
\ No newline at end of file
{
"usingComponents": {
},
"navigationBarTitleText": "智慧党建",
"navigationStyle":"custom"
}
\ No newline at end of file
<!--index.wxml-->
<view class="webview-container">
<view class="navbar" style="height:{{navHeight}}px; ">
<view class="topInfo" style="margin-top:{{customTop}}px;height:{{customHeight}}px;">
<view class="joinCocelal">
<text style="font-size: 17px;">智慧党建</text>
</view>
<view class="searchCoceral">
<icon class="iconfont icon-search'}}" bindtap="changePassword"></icon>
<input class="nav-bar-input" type="text" placeholder="输入搜索关键词"
bindfocus="toSearch" placeholder-class="title_input" />
</view>
</view>
</view>
<!-- 轮播图 -->
<view style="margin-bottom: 20px;margin-top:{{swiperHeight}}px;">
<swiper autoplay="true" duration="2000" circular="true" interval="8000" style="height: 160px;">
<block wx:for="{{homeBannerList}}" wx:key="id">
<swiper-item>
<image src="{{item.bannerPath}}" class="swiper-img" mode="aspectFill"></image>
<view class="swiper-tit">{{item.imgTitle}}</view>
</swiper-item>
</block>
</swiper>
</view>
<!-- 导航 -->
<view class="mid-out">
<view class="nav-list">
<view class="nav-out" wx:for="{{navLists}}" wx:key="id">
<navigator url="{{item.path}}" open-type="{{item.type=='train'?'switchTab':'navigate'}}">
<view class="nav-item">
<image src="{{item.imgPath}}" mode="aspectFill" class="imgi"></image>
<text>{{item.showName}}</text>
</view>
</navigator>
</view>
</view>
</view>
<!-- 七个“虹” -->
<!-- <view style="width: 92%;margin: 0 auto; margin-bottom: 15px;">
<image style="width:100%;height: 110px;" src="./../../static/home/link-bg.png" mode="scaleToFill" />
</view> -->
<!-- 精选资讯 -->
<view>
<view class="new-tit">
<text class="tit"></text>
精选资讯
</view>
<view class="new-out">
<block wx:for="{{newsList}}" wx:key="id">
<view class="new-list" data-item="{{item}}" bind:tap="handleTo">
<image style="width: 40%;height:100px;" src="{{item.logoPath}}" mode="scaleToFill" />
<view class="new-item">
<view class="new-font">{{item.fileName}}</view>
<view style="color: #999;font-size: 12px;">
<text style="margin-right: 5px;">{{item.author}}</text>
{{item.releaseTime}}
</view>
</view>
</view>
</block>
</view>
</view>
</view>
\ No newline at end of file
/* 页面样式 */
page {
height: 100%;
width: 100%;
}
/* web-view容器 */
.webview-container {
width: 100%;
min-height: 100vh;
padding-bottom: 20px;
/* 或使用 flex 布局 */
}
/* 自定义顶部栏 */
.navbar {
width: 100%;
display: flex;
align-items: center;
background-color: #C02B1E;
position: fixed;
top: 0px;
left: 0;
z-index: 10001;
}
.title_input {
font-size: 12px;
color: #fff;
}
.joinCocelal {
font-size: 18px;
color: #fff;
margin-right: 20px;
}
.topInfo {
width: 100%;
display: flex;
align-items: center;
padding-bottom: 8px;
padding-left: 10px;
}
.searchCoceral {
width: 40%;
display: flex;
background-color: rgba(255, 255, 255, 0.25);
border-radius: 20px;
padding: 3px 4px;
}
@font-face {
font-family: 'iconfont';
/* Project id 4769328 */
src: url('//at.alicdn.com/t/c/font_4769328_yh81e4ynuk.woff2?t=1740103917592') format('woff2'),
url('//at.alicdn.com/t/c/font_4769328_yh81e4ynuk.woff?t=1740103917592') format('woff'),
url('//at.alicdn.com/t/c/font_4769328_yh81e4ynuk.ttf?t=1740103917592') format('truetype');
}
.iconfont {
font-family: 'iconfont';
font-size: 14px;
margin-top: -6px;
color: #FFF;
margin-left: 8px;
}
.icon-search::before {
content: '\e617';
}
/* 轮播图 */
.swiper-img {
width: 100%;
height: 100%;
}
.swiper-tit {
width: 100%;
text-align: center;
position: absolute;
bottom: 0px;
left: 0px;
color: #fff;
z-index: 10001;
text-overflow: ellipsis;
white-space: nowrap;
overflow: hidden;
font-size: 12px;
padding: 5px 8px;
background: linear-gradient(180deg, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4) 50%, #000000 100%);
box-shadow: 2px;
box-sizing: border-box;
}
/* 导航栏 */
.mid-out {
background-color: #FFFFFF;
border-radius: 5px;
width: 98%;
margin: 0 auto;
padding-bottom: 10px;
margin-bottom: 10px;
margin-top: -15px;
}
.nav-list {
display: flex;
flex-wrap: wrap;
}
.nav-out {
width: 25%;
margin-top: 15px;
}
.nav-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 13px;
}
.imgi {
width: 45px;
height: 45px;
}
/*精选资讯 */
.new-tit {
width: 92%;
margin: 0 auto;
font-size: 16px;
font-weight: 600;
margin-bottom: 15px;
}
.tit {
display: inline-block;
width: 9px;
height: 18px;
background: linear-gradient(180deg, #fe742b, #fc5b2b 100%);
border-radius: 8px;
margin-right: 5px;
}
.new-out {
width: 90%;
margin: 0 auto;
}
.new-list {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.new-font {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
}
.new-item {
width: 58%;
height: 98px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
\ No newline at end of file
const TOKEN_KEY = 'auth_token';
const TOKEN_EXPIRY = 30 * 24 * 60 * 60 * 1000; // 30天有效期
const md5 = require('/miniprogram_npm/md5/index.js');
const {
sm2
} = require('/miniprogram_npm/sm-crypto/index.js');
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
showPassword: true,
account: '',
password: '',
captchaVal: '',
captchaKey: '',
captchaImgUrl: '',
},
// 生命周期函数 - 检查本地token
onLoad() {
this.getCaptchaKey()
const tokenData = wx.getStorageSync(TOKEN_KEY);
if (tokenData && Date.now() < tokenData.expiry) {
this.redirectToHome();
}
},
accountBindinput: function (e) {
this.setData({
account: e.detail.value
})
},
passwordBindinput: function (e) {
this.setData({
password: e.detail.value
})
},
changePassword: function () {
this.setData({
showPassword: !this.data.showPassword
})
},
captchaValBindinput: function (e) {
this.setData({
captchaVal: e.detail.value
})
},
// 获取验证码
getCaptchaKey() {
let baseUrl =
'https://hqjddj.shanghaiairport.com/system/api/public/getCaptcha?companyCode=zhdj&siteCode=edu&captchaKey=';
let num = Math.floor(Math.random() * 999999)
.toString()
.padStart(6, "0")
this.setData({
captchaKey: num,
captchaImgUrl: baseUrl + num
});
},
generateCharacter(n) {
var chars = [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
];
var res = "";
for (var i = 0; i < n; i++) {
var id = Math.ceil(Math.random() * 35);
res += chars[id];
}
return res;
},
getCurrentDay() {
let date = "";
date = moment(new Date()).format("YYYYMMDD");
return date;
},
// 登录处理
async handleLogin() {
const public_key =
"047214fe3a249b75b6ba92ee494e0a8a68c0a19893a480b3c28bf06cd5b7d621243c7f6704caa3b43ade6be15de11cabd185611a9edfdcf1b11d7a2478c67b4c1c";
const private_key =
"00a2bbe941a177ca9f200d1c4d37e8f0b43b9cd2ea662304a05c064c6416e74d49";
let salt = "";
let date = "";
let key = "";
let sign = "";
let password = "";
let account = "";
salt = this.generateCharacter(16);
date = this.getCurrentDay();
password = sm2.doEncrypt(this.data.password + salt, public_key, 1);
account = sm2.doEncrypt(this.data.account + salt, public_key, 1);
password = "04" + password;
account = "04" + account;
if (salt && date) {
key = salt + date;
}
sign =
"account=" +
account +
"&password=" +
password +
"&salt=" +
salt +
"&key=" +
key;
let parms = {
account: account,
password: password,
salt: salt,
sign: md5(sign),
languageCode: 'zh-cn', //新增国际化-cwj-152
terminalType: '2',
captchaVal: this.data.captchaVal,
captchaKey: this.data.captchaKey,
};
const _this = this
wx.request({
url: 'https://hqjddj.shanghaiairport.com/system/api/loginApp?companyCode=zhdj&siteCode=edu',
method: 'POST',
data: parms,
success(res) {
if (res.data.code === "1000") {
_this.saveToken(res.data.data.Authorization);
_this.redirectToHome(res.data.data.userInfo);
} else {
let textInfo = {
"account.not.exist": "账号不存在",
"pwd.error.times": "您已连续输错5次登录密码,账号已被锁定,需5分钟后自动解锁,或联系系统管理员",
"pwd.error.times4": "密码错误!您还有1次机会",
"pwd.error.times3": "密码错误!您还有2次机会",
"pwd.error.times5": "密码错误!您还有0次机会",
"pwd.error.times2": "密码错误!您还有3次机会",
"pwd.error.times1": "密码错误!您还有4次机会",
"img.verify.code.not.correct": "校验码输入不正确",
"img.verify.code.expired": "校验码已过期",
"account.pwd.error": "用户名或密码错误",
"not.site.access.auth": "没有站点访问权限",
}
wx.showToast({
title: textInfo[res.data.subMsg],
icon: 'none',
success:()=>{
_this.getCaptchaKey()
}
});
}
}
})
},
// AES加密密码(需要配置加密密钥)
encryptPassword() {
const key = CryptoJS.enc.Utf8.parse('16位加密密钥');
const encrypted = CryptoJS.AES.encrypt(
this.data.password,
key, {
mode: CryptoJS.mode.ECB
}
);
return encrypted.toString();
},
// Token存储
saveToken(token) {
wx.setStorageSync(TOKEN_KEY, {
token: token,
expiry: Date.now() + TOKEN_EXPIRY
});
},
// 跳转到首页
redirectToHome(item) {
if (item?.firstLogin) {
wx.switchTab({
url: '/pages/changePsd/index'
});
} else {
wx.switchTab({
url: '/pages/home/index'
});
}
}
});
\ No newline at end of file
{
"usingComponents": {
}
}
\ No newline at end of file
<view class="login-out">
<view class="top-out">
<image src="../../static/login/login-icon.png" mode="" class="top-img">
</image>
<view class="login-tit">
机电e先锋
</view>
<view class="login-tit1">
智慧党建平台
</view>
</view>
<view class="input-out">
<!-- 用户名 -->
<view class="login-input">
<view class="uni-input-wrapper">
<image style="width: 24px;height: 24px;" src="./../../static/login/login-user.png" mode="aspectFill" />
<input class="uni-input" type="text" bindinput="accountBindinput" placeholder="请输入用户名" placeholder-style="color:#9E9E9E;" />
</view>
</view>
<!-- 密码 -->
<view class="login-input">
<view class="uni-input-wrapper">
<image style="width: 24px;height: 24px;" src="./../../static/login/login-pwd.png" mode="aspectFill" />
<input class="uni-input" bindinput="passwordBindinput" placeholder="请输入密码" placeholder-style="color:#9E9E9E;" password="{{showPassword}}" />
<icon class="{{showPassword ? 'iconfont icon-eye' : 'iconfont icon-activeEye'}}" bindtap="changePassword"></icon>
</view>
</view>
<!-- 验证码 -->
<view class="login-input">
<view class="uni-input-wrapper" style="display: flex;align-items: center;">
<image style="width: 24px;height: 24px;" src="./../../static/login/login-captcha.png" mode="aspectFill" />
<input class="uni-input" bindinput="captchaValBindinput" placeholder="请输入验证码" placeholder-style="color:#9E9E9E;" />
<image style="width: 100px;height: 33px;" src="{{captchaImgUrl}}" mode="aspectFill" bind:tap="getCaptchaKey"></image>
</view>
</view>
<view class="login-input" style="border: 0;">
<button style="width:100%;" class="login-btn" bindtap="handleLogin">登录</button>
</view>
</view>
</view>
\ No newline at end of file
.login-out {
width: 100%;
height: 100vh;
background-image: url('https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=login-bg.png');
background-size: 100%;
background-repeat: no-repeat;
}
.top-out {
width: 500rpx;
height: 450rpx;
padding-top: 50px;
margin: 0 auto;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.top-img {
width: 65px;
height: 65px;
z-index: 100001;
margin-bottom: 20px;
}
.login-tit {
font-size: 24px;
color: #dd524d;
text-align: center;
font-weight: bold;
margin-bottom: 10px;
}
.login-tit1 {
font-size: 14px;
color: #dd524d;
text-align: center;
margin-bottom: 25px;
font-weight: bold;
}
.input-out {
width: 88%;
margin: 0 auto;
}
.login-input {
height:40px;
border: 1px solid red;
border-radius: 4px;
margin-bottom: 25px;
}
.uni-input-wrapper {
height:100%;
padding:5px;
/* #ifndef APP-NVUE */
display: flex;
align-items: center;
/* #endif */
background-color: #FFFFFF;
border-radius: 4px;
box-sizing: border-box;
}
.uni-icon {
font-size: 24px;
font-weight: normal;
font-style: normal;
width: 24px;
height: 24px;
line-height: 24px;
color: #999999;
}
.uni-eye-active {
color: #007AFF;
}
@font-face {
font-family: 'iconfont'; /* Project id 4769328 */
src: url('//at.alicdn.com/t/c/font_4769328_p50bw4qs20c.woff2?t=1739931119836') format('woff2'),
url('//at.alicdn.com/t/c/font_4769328_p50bw4qs20c.woff?t=1739931119836') format('woff'),
url('//at.alicdn.com/t/c/font_4769328_p50bw4qs20c.ttf?t=1739931119836') format('truetype');
}
.iconfont{
font-family: 'iconfont';
font-size: 25px;
color:#9E9E9E;
}
.icon-activeEye::before{
content: '\ebcc';
}
.icon-eye::before{
content: '\ebcd';
}
.uni-input {
height: 28px;
line-height: 28px;
font-size: 15px;
padding: 0px;
margin-left:5px;
flex: 1;
background-color: #FFFFFF;
}
.login-btn {
border-radius: 4px;
background-color: #dd524d;
color: #FFFFFF;
}
const TOKEN_KEY = 'auth_token';
const TOKEN_EXPIRY = 7 * 24 * 60 * 60 * 1000; // 7天有效期
const CryptoJS = require('./crypto-js'); // 需要引入加密库
Page({
data: {
account: '',
password: '',
captcha: '',
captchaKey:'',
isCounting: false, // 验证码倒计时状态
countdown: 60, // 倒计时秒数
isLoading: false // 登录按钮加载状态
},
// 生命周期函数 - 检查本地token
onLoad() {
const tokenData = wx.getStorageSync(TOKEN_KEY);
this.setData({ captchaKey: Math.floor(Math.random() * 999999)
.toString()
.padStart(6, "0")});
if (tokenData && Date.now() < tokenData.expiry) {
this.redirectToHome();
}
},
// 输入事件处理
onAccountInput(e) {
this.setData({ account: e.detail.value.trim() });
},
onPasswordInput(e) {
this.setData({ password: e.detail.value.trim() });
},
onCaptchaInput(e) {
this.setData({ captcha: e.detail.value.trim() });
},
// 获取验证码逻辑
async getCaptcha() {
if (this.data.isCounting) return;
this.startCountdown();
try {
const res = await wx.request({
url: 'https://hqjddj.shanghaiairport.com/system/api//public/getCaptcha?companyCode=zhdj&siteCode=edu&captchaKey='+captchaKey,
method: 'GET',
});
if (res.data) {
wx.showToast({ title: '验证码已发送' });
console.log(res.data,'验证码')
} else {
wx.showToast({ title: res.data.msg || '发送失败', icon: 'none' });
}
} catch (error) {
wx.showToast({ title: '请求失败', icon: 'none' });
}
},
// 验证码倒计时控制
startCountdown() {
this.setData({ isCounting: true });
const timer = setInterval(() => {
if (this.data.countdown <= 1) {
clearInterval(timer);
this.setData({
isCounting: false,
countdown: 60
});
return;
}
this.setData({ countdown: this.data.countdown - 1 });
}, 1000);
},
// 登录处理
async handleLogin() {
if (this.data.isLoading) return;
this.setData({ isLoading: true });
try {
const res = await wx.request({
url: 'https://hqjddj.shanghaiairport.com/system/api/loginApp?companyCode=zhdj&siteCode=edu',
method: 'POST',
data: {
account: this.data.account,
password: this.encryptPassword(),
captcha: this.data.captcha,
captchaKey: this.data.captchaKey,
captchaVal: this.data.captchaVal,
}
});
this.setData({ isLoading: false });
if (res.data.code === 200) {
this.saveToken(res.data.data.token);
this.redirectToHome();
} else {
wx.showToast({ title: res.data.msg || '登录失败', icon: 'none' });
}
} catch (error) {
this.setData({ isLoading: false });
wx.showToast({ title: '网络异常', icon: 'none' });
}
},
// AES加密密码(需要配置加密密钥)
encryptPassword() {
const key = CryptoJS.enc.Utf8.parse('16位加密密钥');
const encrypted = CryptoJS.AES.encrypt(
this.data.password,
key,
{ mode: CryptoJS.mode.ECB }
);
return encrypted.toString();
},
// Token存储
saveToken(token) {
wx.setStorageSync(TOKEN_KEY, {
token: token,
expiry: Date.now() + TOKEN_EXPIRY
});
},
// 跳转到首页
redirectToHome() {
wx.switchTab({
url: '/pages/home/index'
});
}
});
\ No newline at end of file
Page({
data: {
message:"<div style='text-indent:2em;'>为推动党建管理的数字化、党建工作的可视化,机电信息保障部党委(以下简称部党委)着力开发“党建信息平台”(以下简称平台)——“机电e先锋”,通过微信小程序方式,实现打破时间和空间的限制,将先进的信息技术融入到党建日常工作中,有效提升信息传达顺畅度,提高基层党建工作规范化水平。</div><div style='text-indent:2em;'>同时,通过使用小程序,加强党员教育管理工作,落实教育数字化战略行动,切实增强员工对党务工作的感受度,让基层党建工作开展地更加灵活高效,从而进一步提升党建效能、激发党建活力、筑牢党建堡垒,促进各支部和党员主动融入部门党建,共享党建资源,共同携手进步。</div>"
},
onLoad: function (options) {
},
})
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "关于智慧党建"
}
\ No newline at end of file
.out {
width: 100%;
min-height: 100vh;
background: linear-gradient(0deg, #ff9286 0%, #d23a29),
linear-gradient(180deg, rgba(255, 255, 255, 0) 59%, #f5f5f5 100%),
linear-gradient(0deg, rgba(210, 58, 41, 0) 0%, #d23a29);
box-sizing: border-box;
.content {
width: 90%;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
color: #333;
background-color: #fff;
border-radius: 10px;
.footer {
margin-top: 15px;
display: flex;
justify-content: flex-end;
font-size: 14px;
}
}
}
\ No newline at end of file
<view class="out">
<view class="content">
<rich-text class="content" nodes="{{message}}" />
<view class="footer">机电信息保障部党委</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
searchResultList: []
},
onLoad() {
get(url.myHistory,'').then(res=>{
res.data.classificationVOList.map(item=>{
item.createTime = moment(item.createTime).format("YYYY-MM-DD HH:mm")
})
this.setData({
searchResultList:res.data.classificationVOList
})
})
},
newsItemClick(e) {
const data = e.currentTarget.dataset.item;
wx.navigateTo({
url: `/pages/NewsMessage/news/index?id=${data.id}`
});
},
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "浏览历史"
}
\ No newline at end of file
.global-search-result {
padding: 30px;
box-sizing: border-box;
.global-search-result-con {
.result-tit {
color: #000000;
font-size: 18px;
font-weight: 600;
margin-bottom: 10px;
span {
display: inline-block;
width: 8px;
height: 18px;
background: linear-gradient(180deg, #fe742b, #fc5b2b 100%);
border-radius: 10px;
margin-right: 10px;
}
}
.result-content {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.result-content-img{
width: 35%;
}
.result-content-item {
width: 60%;
display: flex;
flex-direction: column;
justify-content: space-between;
.result-content-item-tit {
padding-right: 15px;
font-size: 16px;
color: #000;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
/* 定义文本的行数 */
overflow: hidden;
text-overflow: ellipsis;
margin-bottom: 20px;
}
.result-content-item-bot {
font-size: 14px;
color: #ABABAB;
span {
margin-right: 20px;
}
}
}
}
}
}
\ No newline at end of file
<view class="global-search-result">
<block wx:for="{{searchResultList}}" wx:key="index">
<view class="global-search-result-con">
<view class="result-tit">
<span></span> {{item.name}}
</view>
<block wx:for="{{item.informationVoList}}" wx:key="index">
<view class="result-content" bindtap="newsItemClick" data-item="{{item}}">
<view class="result-content-img">
<image src="{{item.logoPath}}" style="width: 100%; height: 82px;"></image>
</view>
<view class="result-content-item">
<view class="result-content-item-tit">
{{item.fileName}}
</view>
<view class="result-content-item-bot">
<text>{{item.author}}</text>
<text>{{formatTime(item.releaseTime)}}</text>
</view>
</view>
</view>
</block>
</view>
</block>
</view>
\ No newline at end of file
const TOKEN_KEY = 'auth_token';
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
Page({
data: {
userImage: './../../static/mine/shuijiao.jpg',
userName: '',
companyName: '',
navLists: [],
},
onLoad() {
const _this = this
get(url.userInfoApi).then(res => {
this.setData({
userName: res.data.fullName,
companyName: res.data.companyName,
userImage:res.data.headPortrait
})
})
post(url.getMineItemsApi, {}).then(res => {
let items = res.data.data2;
items.map(item => {
switch (item.name) {
case '修改密码':
item['path'] = "/pages/changePsd/index"
break;
case '我要留言':
item['path'] = "/pages/mine/myLeaveMessage/index"
break;
case '党委书记信箱':
item['path'] = "/pages/mine/messageBox/index?type=1"
break;
case '纪检信箱':
item['path'] = "/pages/mine/messageBox/index?type=2"
break;
case '我的诉求':
item['path'] = "/pages/mine/myAppeal/index?type=1"
break;
case '我的信箱':
item['path'] = "/pages/mine/myAppeal/index?type=2"
break;
case '我的评论':
item['path'] = "/pages/mine/myComment/index"
break;
case '我的投稿':
item['path'] = "/pages/mine/myContribute/index"
break;
case '我的培训':
item['path'] = "/pages/trainingAndTest/index?type=1"
break;
case '我的测试':
item['path'] = "/pages/trainingAndTest/index?type=2"
break;
case '我参与的问卷':
item['path'] = "/pages/workTask/index?type=1"
break;
case '我的活动':
item['path'] = "/pages/activity/index"
break;
default:
break;
}
})
this.setData({
navLists: items
})
})
},
accountBindinput: function (e) {
this.setData({
account: e.detail.value
})
},
goDetailPage(){
wx.navigateTo({
url: '/pages/mine/aboutZhdj/index',
})
},
goBack() {
wx.reLaunch({
url: '/pages/login/index'
});
wx.setStorageSync(TOKEN_KEY, {
token: '',
expiry: ''
});
},
handleTo(){
wx.navigateTo({
url: '/pages/mine/userInfo/index',
})
}
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "个人中心"
}
\ No newline at end of file
<view style="height: 100vh; background-color: #f5f5f5;padding-bottom: 15px;">
<view class="top-out">
<view class="top-user" >
<image src="{{userImage}}" mode="aspectFill" class="user-img"></image>
<view>
<view class="user-name">{{userName}}</view>
<view class="user-name">{{companyName}}</view>
</view>
<view class="to-info" bind:tap="handleTo">
<image src="/static/tomore.png" mode="aspectFill" style="width: 100%;height: 100%;"/>
</view>
</view>
<view class="collect">
<navigator url="/pages/mine/myCollection/index" class="item item1">
<image src="./../../static/mine/collect-icon.png" mode="aspectFill" class="item-img"></image>
<text>我的收藏</text>
</navigator>
<navigator url="/pages/mine/browsingHistory/index" class="item">
<image src="./../../static/mine/history-icon.png" mode="aspectFill" class="item-img"></image>
<text>浏览历史</text>
</navigator>
</view>
</view>
<view class="study-record-info">
<view class="study-item">
<view style='display: flex;align-items: center;'>
<image src="./../../static/mine/jinb-icon.png" mode="aspectFill" style="width: 30px;height: 30px; margin-right: 5px;" />
<view style="font-size: 15px; font-weight: bold;">
做任务,赢积分
</view>
</view>
<view style="display: flex;">
<navigator url="/pages/mine/myintegral/index" class="study-jf">
我的积分
</navigator>
</view>
</view>
</view>
<view class="mid-out">
<view class="nav-list">
<view class="nav-out" wx:for="{{navLists}}" wx:key="id">
<navigator url="{{item.path}}" open-type="{{item.code=='px'?'switchTab':'navigate'}}">
<view class="nav-item">
<image src="{{item.logoImg}}" mode="aspectFill" class="imgi"></image>
<text>{{item.name}}</text>
</view>
</navigator>
</view>
</view>
</view>
<view class="list-out">
<view class="list-panel-h" bindtap="goDetailPage">
<text class="list-panel-text">关于智慧党建</text>
<image style="width: 14px;height: 14px;" src="./../../static/tomore.png" mode="aspectFill" />
</view>
</view>
<view class="btn" bindtap="goBack">
退出登录
</view>
</view>
\ No newline at end of file
/* pages/mine/index.wxss */
.top-out {
width: 100%;
height: 160px;
background-image: url('https://hqjddj.shanghaiairport.com/api/v1/buckets/wmy/objects/download/?preview=true&prefix=ming-bg.png');
background-repeat: no-repeat;
background-size: 100% 100%;
padding-top: 10%;
}
.top-user {
display: flex;
align-items: center;
margin-left: 7%;
margin-bottom: 25px;
}
.user-img {
width: 60px;
height: 60px;
border-radius: 50%;
margin-right: 15px;
}
.to-info{
width: 20px;
height: 20px;
margin-left: auto;
margin-right:20px ;
}
.user-name {
margin-top: 5px;
color: #fff;
}
.collect {
width: 100%;
margin: 0 auto;
display: flex;
align-items: center;
}
.item {
width: 50%;
display: flex;
align-items: center;
justify-content: center;
color: #fff;
}
.item-img {
width: 16px;
height: 16px;
margin-right: 5px;
}
.item1 {
border-right: 1px solid #fff;
}
.mid-out {
background-color: #FFFFFF;
border-radius: 5px;
width: 90%;
margin: 0 auto;
padding-bottom: 10px;
margin-bottom: 10px;
margin-top: -15px;
}
.nav-list {
display: flex;
flex-wrap: wrap;
}
.nav-out {
width: 33%;
margin-top: 15px;
}
.nav-item {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
font-size: 13px;
}
.imgi {
width: 45px;
height: 45px;
}
.list-out {
width: 90%;
margin: 0 auto;
background-color: #FFFFFF;
border-radius: 5px;
margin-bottom: 10px;
}
.list-panel-h {
height: 35px;
padding: 10rpx 20rpx;
border-bottom: 1px solid #F4F4F4;
display: flex;
justify-content: space-between;
align-items: center;
}
.list-panel-icon {
font-weight: normal;
}
.btn {
width: 90%;
height: 40px;
line-height: 40px;
text-align: center;
margin: 0 auto;
background-color: #FFFFFF;
border-radius: 5px;
color: #9F9F9F;
font-size: 17px;
margin-bottom: 20px;
}
.study-record-info {
width: 96%;
margin: 0 auto;
height: 60px;
border-radius: 10px;
background: rgb(255, 255, 255);
box-shadow: 0px 4px 8px 0px rgba(0, 0, 0, 0.1);
position: relative;
top: -30px;
}
.study-item {
width: 90%;
margin: 0 auto;
height: 60px;
display: flex;
align-items: center;
justify-content: space-between;
}
.study-jf {
padding: 5px 6px;
background: linear-gradient(90deg, #d23a29, #eb6c53 100%);
border-radius: 25px;
color: #fff;
font-size: 14px;
text-align: center;
margin-left: 8px;
}
.study-jf1 {
background: rgba(230, 98, 74, 0.10);
color: #E6624A;
}
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
Page({
data: {
activeId: 0,
targetFrom: "意见建议",
type: '',
mailList: [],
},
onLoad: function (options) {
// options.type 1 党委书记信箱 2纪检信箱
if (options.type == '2') {
this.setData({
mailList: [{
name: "意见建议",
id: 1
},
{
name: "线索提供",
id: 2
},
{
name: "举报",
id: 3
},
]
})
wx.setNavigationBarTitle({
title: "纪检信箱"
});
} else {
wx.setNavigationBarTitle({
title: "党委书记信箱"
});
this.setData({
mailList: [{
name: "意见建议",
id: 1
},
{
name: "反映问题",
id: 2
},
{
name: "寻求帮助",
id: 3
},
]
})
}
this.setData({
type: options.type
})
},
onReady: function () {
},
handleClick(e) {
let val = e.currentTarget.dataset;
console.log(val)
if (this.data.activeId != val.index) {
this.setData({
activeId: val.index,
targetFrom: val.item.name,
});
}
},
formSubmit(e) {
const uploadData = this.selectComponent('#upload')?.data;
let videos = [];
let params = {
fileName: e.detail.value.fileName,
content: e.detail.value.content,
ossPicUrl: JSON.stringify(uploadData.uploadFile),
ossVideoUrl: JSON.stringify(videos),
remark: e.detail.value.remark,
targetFrom: this.data.targetFrom, //来信目的
anonymousFlag: e.detail.value.anonymousFlag ? 1 : 0, //是否匿名:1是,0否
};
if (!e.detail.value.fileName) {
return wx.showToast({
title: '请输入标题',
icon: 'error',
})
}
if (!e.detail.value.content) {
return wx.showToast({
title: '请输入具体内容',
icon: 'error',
})
}
if (this.data.type == 1 && !e.detail.value.remark) {
return wx.showToast({
title: '请输入期望结果',
icon: 'error',
})
}
if (this.data.type == 1) {
post(url.dwsystemMailboxApi, params).then(res => {
wx.showToast({
title: '提交成功',
icon: 'success',
success: () => {
wx.navigateBack()
}
})
})
} else {
post(url.systemMailboxApi, params).then(res => {
wx.showToast({
title: '提交成功',
icon: 'success',
success: () => {
wx.navigateBack()
}
})
})
}
},
switchChange(e) {
console.log(e.detail)
},
})
\ No newline at end of file
{
"usingComponents": {
"upload-media":"/pages/components/uploadMedia/index"
}
}
\ No newline at end of file
/* pages/mine/messageBox/index.wxss */
.form-out {
padding: 10px;
box-sizing: border-box;
.item-out {
border-radius: 10px;
padding: 20px;
background-color: #fff;
margin-bottom: 20px;
.item-input {
width: 100%;
min-height: 40px;
// border: 1px solid rgb(204, 202, 202);
padding-left: 5px;
border-radius: 5px;
}
}
}
.unactive-box {
height: 42px;
line-height: 42px;
background-color: #f7f7f7;
text-align: center;
color: #454343;
border-radius: 40px;
}
.active-box {
height: 42px;
line-height: 42px;
background: rgba(253, 63, 52, 0.05);
border: 1px solid #f3ab9f;
border-radius: 4px;
text-align: center;
color: #454343;
border-radius: 40px;
}
.form-btn {
min-width: 100%;
text-align: center;
color: #fff;
font-size: 18px;
padding: 10px 0;
border-radius: 4px;
background: linear-gradient(270deg, #eb6c53 0%, #d23a29);
}
\ No newline at end of file
<view style="background-color: #f5f5f5;">
<view class="form-out">
<form catchsubmit="formSubmit">
<view class="item-out">
<view style="margin-bottom: 20px;">来信目的 <text style="color: red;">*</text> </view>
<view style="display: flex;">
<view wx:for="{{mailList}}" wx:key="id" style="width:30%;">
<view data-item="{{item}}" data-index="{{index}}" class="{{ activeId==index ? 'active-box' : 'unactive-box'}}" bind:tap="handleClick">
{{item.name}}
</view>
</view>
</view>
</view>
<view class="item-out">
<view style="margin-bottom: 20px;">标题 <text style="color: red;">*</text> </view>
<view style="display: flex;">
<input name="fileName" class="item-input" type="text" placeholder="标题需15字以内" maxlength="15" />
</view>
</view>
<view class="item-out">
<view style="margin-bottom: 20px;">具体内容 <text style="color: red;">*</text> </view>
<view style="display: flex;">
<textarea name="content" class="item-input" placeholder="请输入具体内容" maxlength="500" />
</view>
</view>
<view class="item-out" wx:if="{{type == '1'}}">
<view style="margin-bottom: 20px;">期望结果 <text style="color: red;">*</text> </view>
<view style="display: flex;">
<textarea name="remark" class="item-input" placeholder="请输入期望结果" />
</view>
</view>
<view class="item-out">
<view>
<view>上传附件</view>
<upload-media id="upload"></upload-media>
</view>
</view>
<view class="item-out">
<view style="display: flex;justify-content: space-between;">
<view style="margin-bottom: 20px;">是否匿名 <text style="color: red;">*</text> </view>
<switch name="anonymousFlag" checked="{{switch1Checked}}" bindchange="switchChange" />
</view>
</view>
<view style="width: 100%;">
<button class="form-btn" formType="submit">提交</button>
</view>
</form>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../../utils/request');
import url from '../../../../utils/urlconfig';
Page({
data: {
type:"",
appealItem:{}
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
this.setData({
type:options.type
})
if (options.type == 3) {
get(url.myAppealDetailApi,{
id:options.id
}).then(res=>{
res.data["ossUrl"] = JSON.parse(res.data.ossUrl);
this.setData({
appealItem:res.data
})
console.log(this.data.appealItem)
})
} else {
get(url.myMailboxApi,{
id:options.id
}).then(res=>{
res.data["ossPicUrl"] = JSON.parse(res.data.ossPicUrl);
this.setData({
appealItem:res.data
})
})
}
},
//图片预览
previewImage(e) {
const index = e.currentTarget.dataset.index;
const imageList = this.data.appealItem.ossUrl;
wx.previewImage({
current: imageList[index], // 当前显示图片的http链接
urls: imageList // 需要预览的图片http链接列表
});
},
})
\ No newline at end of file
{
"usingComponents": {}
}
\ No newline at end of file
//信箱详情
.mailbox-detail-out {
width: 92%;
margin: 0 auto;
padding-bottom: 20px;
.detail-items {
display: flex;
align-items: center;
padding: 20px;
}
.item-tit {
width: 28%;
color: #888888;
}
.item-con {
width: 68%;
color: #353535;
}
.items-img{
width: 70px;
height: 70px;
margin-right: 10px;
margin-top: 8px;
.item-img{
width: 70px;
height: 70px;
border-radius: 10px;
}
}
}
\ No newline at end of file
<view style="background-color: #f5f5f5;min-height: 100vh;">
<view class="mailbox-detail-out">
<view style="background-color: #fff;margin-bottom: 20px;">
<view wx:if="{{type == 3}}" class="detail-items">
<view class="item-tit">问题类型</view>
<view class="item-con"> {{appealItem.bizType == 0
? '功能异常'
: appealItem.bizType == 1
? '体验问题'
: appealItem.bizType == 2
? '产品建议'
: '其他'}}</view>
</view>
<view wx:else class="detail-items">
<view class="item-tit">来信目的</view>
<view class="item-con">{{appealItem.targetFrom}}</view>
</view>
<view class="line"></view>
<view class="detail-items">
<view class="item-tit">标题</view>
<view class="item-con">{{type==3? appealItem.name:appealItem.fileName}}</view>
</view>
<view class="line"></view>
<view wx:if="{{type == '3'}}" class="detail-items">
<view class="item-tit">问题或建议</view>
<view class="item-con">{{appealItem.content}}</view>
</view>
<view wx:else class="detail-items">
<view class="item-tit">具体内容</view>
<view class="item-con">{{appealItem.content}}</view>
</view>
<view class="line"></view>
<view class="detail-items" wx:if="{{appealItem.type == 2}}">
<view class="item-tit">期望结果</view>
<view class="item-con">{{appealItem.remark}}</view>
</view>
</view>
<view wx:if="{{type == 3}}" style="padding:20px;background-color: #fff;margin-bottom: 20px;">
<view class="item-tit" style="margin-bottom: 10px;">附件</view>
<view style="display: flex;">
<view wx:for="{{appealItem.ossUrl}}" data-index="{{index}}" wx:key="index" class="items-img">
<image src="{{item}}" alt="" class="item-img" bindtap="previewImage" />
</view>
</view>
</view>
<view wx:else style="padding:20px;background-color: #fff;margin-bottom: 20px;">
<view class="item-tit">附件</view>
<view style="display: flex;">
<view wx:for="{{appealItem.ossPicUrl}}" data-index="{{index}}" wx:key="index" class="items-img">
<image src="{{item}}" alt="" class="item-img" />
</view>
</view>
</view>
<view class="detail-items" style="background-color: #fff;margin-bottom: 20px;">
<view class="item-tit">是否匿名</view>
<view class="item-con">
{{appealItem.anonymousFlag == 1 ? "是" : "否"}}
</view>
</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
appeallist: []
},
onLoad: function (options) {
if (options.type == 2) {
wx.setNavigationBarTitle({
title: '我的信箱'
});
} else {
wx.setNavigationBarTitle({
title: '我的诉求'
});
}
get(url.myAppealListApi, {
pageNo: 1,
pageSize: 20
}).then(res => {
let list = res.data.records;
list.map(item => {
item.submitTime = moment(item.submitTime).format("YYYY年MM月DD日 HH:mm")
})
if (options.type == 2) {
list = list.filter(item => item.type !== 3);
console.log(list)
}
this.setData({
appeallist: list
})
})
},
handleTo(e) {
let item = e.currentTarget.dataset.item;
wx.navigateTo({
url: '/pages/mine/myAppeal/detail/index?id=' + item.id + `&type=` + item.type,
})
}
})
\ No newline at end of file
{
"usingComponents": {}
}
\ No newline at end of file
.mailbox-out {
padding-top: 20px;
width: 90%;
margin: 0 auto;
height: 100%;
.items {
.item-tit {
font-size: 16px;
margin-bottom: 20px;
}
.item-ion {
display: flex;
align-items: center;
.item-time {
font-size: 14px;
color: #999;
margin-right: 30px;
}
.item-source {
font-size: 14px;
color: #999;
}
}
}
.line{
margin-top: 10px;
background-color: #ddd2d2;
width: 100%;
height: 1px;
}
}
.detail-out{
background: #f7f7f7;
height: 100vh;
.tit-top {
height: 90px;
display: flex;
justify-content: space-between;
align-items: center;
background: linear-gradient(270deg, #ee4e3c 0%, #d23a29);
margin-bottom: 20px;
background-color: #ffffff;
.back-icon {
width: 38px;
height: 38px;
padding-left: 20px;
}
}
}
<!--pages/mine/myAppeal/index.wxml-->
<view class="mailbox-out">
<block wx:for="{{appeallist}}" wx:key="index">
<view
style="margin-bottom: 20px;"
bindtap="handleTo"
data-item="{{item}}"
>
<view class="items">
<view class="item-tit">{{item.fileName}}</view>
<view class="item-ion">
<view class="item-time">
{{item.submitTime}}
</view>
<view class="item-source">
{{item.type == 1 ? '纪检信箱' : item.type == 2 ? '党委书记信箱' : '我的留言'}}
</view>
</view>
</view>
<view class="line"></view>
</view>
</block>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
searchResultList: []
},
onLoad() {
get(url.myCaseFavorites,{
pageNo:1,pageSize:50
}).then(res=>{
res.data.records.map(item=>{
item.submitTime = moment(item.submitTime).format("YYYY-MM-DD HH:mm")
})
this.setData({
searchResultList:res.data.records
})
})
},
newsItemClick(e) {
const data = e.currentTarget.dataset.item;
wx.navigateTo({
url: `/pages/NewsMessage/news/index?id=${data.favoriteId}`
});
},
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "我的收藏"
}
\ No newline at end of file
.global-search-container {
padding: 30px;
box-sizing: border-box;
.result-content {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
padding-bottom: 10px;
border-bottom: 1px solid #ccc;
.result-content-item {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.result-content-item-tit {
padding-right: 15px;
font-size: 16px;
color: #000;
margin-bottom: 20px;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2; /* 定义文本的行数 */
overflow: hidden;
text-overflow: ellipsis;
}
.result-content-item-bot {
font-size: 14px;
color: #ababab;
span {
margin-right: 20px;
}
}
}
}
}
<view class="global-search-container">
<block wx:for="{{searchResultList}}" wx:key="*this">
<view class="result-content" bindtap="newsItemClick" data-item="{{item}}">
<view class="result-content-item">
<view>
<view class="result-content-item-tit">{{item.studentCaseTittle}}</view>
<view class="result-content-item-bot">
<text>收藏时间 </text>
<text>{{item.submitTime}}</text>
</view>
</view>
<view>
<image src="/static/tomore.png" mode="aspectFill" style="width: 18px;height: 18px;"/>
</view>
</view>
</view>
</block>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
Page({
data: {
commentList: [],
commentShow: false,
userAvatar:''
},
onLoad() {
post(url.myCommentListApi, {}).then(res => {
let list = res.data.records;
this.setData({
userAvatar:list[0].userAvatar
})
list.forEach((item) => {
if (item.tpCommentReplies.length > 0) {
item.showStatu = true;
} else {
item.showStatu = false;
}
if (item.imageUrls) {
item.imageUrList = JSON.parse(item.imageUrls);
}
});
this.setData({
commentList: list
});
})
},
show(res, i) {
console.log(res.showStatu, '22222');
console.log(this.data.commentList);
},
handleTo(e) {
let i = e.currentTarget.dataset.item;
if (i.bizType == 1) {
wx.navigateTo({
url: `/pages/activity/index?id=${i.trainingProjectId}`
});
} else {
wx.navigateTo({
url: `/pages/NewsMessage/news/index?id=${i.trainingProjectId}`
});
}
},
//图片预览
previewImage(e) {
const index = e.currentTarget.dataset.index;
const imageList = this.data.commentList[index].imageUrList;
wx.previewImage({
current: imageList[index], // 当前显示图片的http链接
urls: imageList // 需要预览的图片http链接列表
});
},
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "我的评论"
}
\ No newline at end of file
.comment-out {
background-color: #f7f7f7;
height: 100vh;
.dis-flex {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 15px;
}
.commit-user-img {
width: 60px;
height: 60px;
margin-right: 15px;
.img {
width: 60px;
height: 60px;
border-radius: 50%;
}
}
.commit-user-img1 {
margin-right: 15px;
.img1 {
width: 35px;
height: 35px;
border-radius: 50%;
}
}
.commit-user-name {
color: #000;
font-weight: 500;
margin-bottom: 8px;
}
.commit-user-time {
color: #ccc;
font-weight: 500;
}
.commit-icon {
width: 15px;
height: 15px;
}
.commit-con {
padding: 10px;
color: #000;
background-color: #f9f9f9;
margin-bottom: 20px;
}
.second-commit {
width: 85%;
margin: 0 auto;
padding: 10px 20px;
background-color: #f9f9f9;
margin-bottom: 20px;
}
.second-commit-con {
color: #000;
}
.commit-more{
margin-bottom: 10px;
}
}
\ No newline at end of file
<view class="comment-out">
<block wx:for="{{commentList}}" wx:key="index">
<view style="margin-bottom: 30px; padding: 30px; background-color: #fff;" >
<view class="dis-flex">
<view class="dis-flex">
<view class="commit-user-img">
<image class="img" src="{{item.userAvatar}}" mode="aspectFill" ></image>
</view>
<view class="user-out">
<view class="commit-user-name">
{{item.commentatorName}}
</view>
<view class="commit-user-time">{{item.createTime}}</view>
</view>
</view>
<view>
<image bindtap="handleTo" data-item="{{item}}" src="./../../../static/tomore.png" mode="aspectFit" class="commit-icon"></image>
</view>
</view>
<view>
<view class="commit-con">{{item.content}}</view>
<block wx:if="{{item.imageUrList && item.imageUrList.length > 0}}">
<block wx:for="{{item.imageUrList}}" wx:key="index">
<image src="{{item}}" mode="aspectFill" data-index="{{index}}" bindtap="previewImage" style="width: 100px; height: 100px;margin-right: 12px;"></image>
</block>
</block>
<block wx:if="{{item.showStatu}}">
<view class="commit-more" bindtap="show" data-res="{{item}}" data-i="{{index}}">
-共{{item.tpCommentReplies.length}}回复-
</view>
</block>
<block wx:if="{{item.showStatu}}">
<block wx:for="{{item.tpCommentReplies}}" wx:key="index">
<view class="second-commit">
<view style="display: flex; align-items: center;">
<view class="commit-user-img1">
<image src="{{item.userAvatar}}" mode="aspectFill" class="img1"></image>
</view>
<view class="commit-user-name" style="font-size:14px;">
{{item.createByFullName}}
</view>
</view>
<view class="second-commit-con">{{item.content}}</view>
</view>
</block>
</block>
</view>
</view>
</block>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
list: [],
showStatu: true,
content: {},
},
onLoad() {
post(url.getContributeMyListApi,{}).then(res=>{
res.data.records.map(item=>{
item.submitTime = moment(item.submitTime).format("YYYY-MM-DD HH:mm")
})
this.setData({
list: res.data.records,
});
})
},
handleClick(e) {
const item = e.currentTarget.dataset.item;
item.ossUrl = JSON.parse(item.ossUrl)
this.setData({
showStatu: false,
content: item
});
console.log(this.data.content)
},
//图片预览
previewImage(e) {
const index = e.currentTarget.dataset.index;
const imageList = this.data.content.ossUrl;
wx.previewImage({
current: imageList[index], // 当前显示图片的http链接
urls: imageList // 需要预览的图片http链接列表
});
},
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "我的投稿"
}
\ No newline at end of file
.contribute-myself-out {
background-color: #f5f5f5;
min-height: 100vh;
.contribute-myself-box {
width: 96%;
margin: 0 auto;
background-color: #fff;
margin-bottom: 30px;
padding: 20px;
display: flex;
justify-content: space-between;
align-items: center;
border-bottom: 1px solid #E5E6E8;
box-sizing: border-box;
.contribute-myself-top {
font-size: 20px;
font-weight: 500;
color: #000;
margin-bottom: 15px;
}
.contribute-myself-bot {
display: flex;
.contribute-bot-item {
font-size: 16px;
color: #ababab;
margin-right: 20px;
}
}
}
}
//投稿详情
.contribute-detail-out {
width: 92%;
margin: 20px auto;
padding-bottom: 30px;
.contribute-detail-box {
padding: 20px 15px;
background-color: #fff;
margin-bottom: 20px;
.top-tit {
font-size: 20px;
font-weight: bold;
color: #000;
margin-bottom: 15px;
}
.user-tit {
color: #999999;
font-size: 32px;
}
.userinfo-box {
margin-top: 30px;
display: flex;
justify-content: space-between;
align-items: center;
.userinfo-name {
color: #666666;
font-size: 20px;
}
}
}
}
<view class="contribute-myself-out">
<!-- 列表展示 -->
<block wx:if="{{showStatu}}">
<view wx:for="{{list}}" wx:key="*this" class="contribute-myself-box" bindtap="handleClick" data-item="{{item}}">
<view style="width: 100%;">
<view class="contribute-myself-top">{{item.fileName}}</view>
<view class="contribute-myself-bot">
<view class="contribute-bot-item">{{item.submitTime}}</view>
<view class="contribute-bot-item">{{item.deptName}}</view>
</view>
</view>
<view style="width: 20px;height: 20px;">
<image src="/static/tomore.png" mode="aspectFill" style="width: 100%;height: 100%;"></image>
</view>
</view>
</block>
<!-- 详情展示 -->
<block wx:else>
<view class="contribute-detail-out">
<view class="contribute-detail-box">
<view class="top-tit">标题</view>
<view style="font-size: 18px;">{{content.fileName}}</view>
</view>
<view class="contribute-detail-box">
<view class="top-tit">正文</view>
<rich-text nodes="{{content.content}}"/>
</view>
<view class="contribute-detail-box">
<view class="top-tit">图片或视频上传</view>
<view>
<block wx:for="{{content.ossUrl}}" data-index="{{index}}" wx:key="index">
<image bindtap="previewImage" data-index="{{index}}" src="{{item}}" style="width: 70px;height: 70px;margin-right:8px;border-radius: 10px;" mode="aspectFill"></image>
</block>
</view>
</view>
<view class="contribute-detail-box">
<view class="userinfo-box">
<view class="userinfo-name">作者</view>
<view style="font-size: 16px; margin-top: 15px;">{{content.author}}</view>
</view>
<view class="userinfo-box">
<view class="userinfo-name">支部和部室</view>
<view style="font-size: 16px; margin-top: 15px;">{{content.deptName}}</view>
</view>
</view>
</view>
</block>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
Page({
data: {
anonymousValue: false,
titleValue: "",
contentValue: "",
bizType: 0,
activeId: 0,
mapList: [{
id: 0,
cnName: "功能异常"
},
{
id: 1,
cnName: "体验问题"
},
{
id: 2,
cnName: "产品建议"
},
{
id: 3,
cnName: "其他"
}
]
},
onLoad() {
},
handleMessageClick(e) {
this.setData({
activeId: e.currentTarget.dataset.index,
bizType: e.currentTarget.dataset.data.id
});
},
handleClick() {
if (!this.data.titleValue) {
wx.showToast({
title: "请输入标题",
icon: "none"
});
return;
}
if (!this.data.contentValue) {
wx.showToast({
title: "请输入问题或建议",
icon: "none"
});
return;
}
if (this.data.contentValue.length < 10) {
wx.showToast({
title: "最少输入 10 字或以上内容",
icon: "none"
});
return;
}
const uploadData = this.selectComponent('#upload')?.data;
let params = {
name: this.data.titleValue,
content: this.data.contentValue,
ossUrl: JSON.stringify(uploadData.uploadFile),
anonymousValue: this.data.anonymousValue ? 1 : 0,
bizType: this.data.bizType
};
post(url.setLeaveMesApi, params).then(res => {
wx.showToast({
title: "提交成功",
icon: "success",
duration:2000,
success: () => {
wx.navigateBack();
}
});
})
},
onTitleChange(e) {
this.setData({
titleValue: e.detail.value
});
},
onContentChange(e) {
this.setData({
contentValue: e.detail.value
});
},
switchChange(e) {
this.setData({
anonymousValue: e.detail.value
});
},
});
\ No newline at end of file
{
"usingComponents": {
"upload-media":"/pages/components/uploadMedia/index"
},
"navigationBarTitleText": "我要留言"
}
\ No newline at end of file
//投稿详情
.contribute-detail-out {
width: 92%;
margin: 30px auto;
padding-bottom: 30px;
.contribute-detail-box {
padding: 20px;
background-color: #fff;
.top-tit {
font-weight: bold;
color: #000;
margin-bottom: 15px;
.red-star {
color: red;
}
span {
color: #9e9e9e;
font-size: 14px;
}
}
}
.mycontribute-box {
background-color: #fff;
width: 100%;
padding-top: 20px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
.item-box {
width: 32%;
margin-bottom: 10px;
height: 50px;
line-height: 50px;
background-color: #f7f7f7;
text-align: center;
color: #454343;
border-radius: 15px;
}
.item-box-active {
background: rgba(253, 63, 52, 0.05);
border: 1px solid #f3ab9f;
}
span {
width: 100%;
color: #e6624a;
}
}
.contribute-detail-btn {
.sumbit-btn {
width: 100%;
text-align: center;
color: #fff;
font-size: 18px;
padding: 10px 0;
border-radius: 4px;
background: linear-gradient(270deg, #eb6c53 0%, #d23a29);
}
}
}
<view class="contribute-detail-out">
<view class="contribute-detail-box">
<view class="top-tit">
问题类型 <text class="red-star">*</text>
</view>
<view class="mycontribute-box">
<block wx:for="{{mapList}}" wx:key="index">
<view class="item-box {{activeId == index ? 'item-box-active' : ''}}" bindtap="handleMessageClick" data-data="{{item}}" data-index="{{index}}">
{{item.cnName}}
</view>
</block>
</view>
</view>
<view class="contribute-detail-box">
<view class="top-tit">
标题 <text class="red-star">*</text>
<text>(15 字以内)</text>
</view>
<input placeholder="请填写您标题" value="{{titleValue}}" bindinput="onTitleChange" allow-clear maxlength="15" style="height: 60px; line-height: 60px;" />
</view>
<view class="contribute-detail-box">
<view class="top-tit">
问题或建议<text class="red-star">*</text>
<text>(10 - 500 字)</text>
</view>
<textarea value="{{contentValue}}" bindinput="onContentChange" placeholder="请填写您的问题或建议" rows="8" maxlength="500" />
</view>
<view class="contribute-detail-box">
<view>
<view class="top-tit">上传图片</view>
<upload-media id="upload"></upload-media>
</view>
<view style="font-size: 14px; color: #9E9E9E">
支持.png.jepg 格式,每张最大 5MB
</view>
</view>
<view class="contribute-detail-box" style="display: flex; justify-content: space-between; align-items: center;">
<view class="top-tit">
是否匿名 <text class="red-star">*</text>
</view>
<switch bindchange="switchChange" />
</view>
<view class="contribute-detail-btn">
<view class="sumbit-btn" bindtap="handleClick">
提交
</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
Page({
data: {
score: "340",
scoreNow: "6",
showBtn: false,
contList: [],
contList1: [{
titleVal: "1分/每日首次登录",
learnType: "point_login"
},
{
titleVal: "1分/每有效阅读文章一篇(阅读时长超过20秒)",
url: "/pages/home/index",
learnType: "point_read"
},
{
titleVal: "5分/每投稿一篇有效内容(审核通过)",
url: "/pages/contribute/index",
learnType: "point_draft"
},
{
titleVal: "3分/每发表一个有效评论(审核通过)",
url: "/pages/home/index",
learnType: "point_comment"
},
{
titleVal: "3分/报名并成功打卡参与活动",
url: "/pages/activity/index",
learnType: "CreditSignDone"
},
{
titleVal: "根据答题分数获得相应积分",
url: "/pages/trainingAndTest/index",
learnType: "CreditExamDone"
}
],
},
onLoad() {
get(url.getPointDetailApi, '').then(res => {
let list = res.data.pointVoList;
list.forEach((item) => {
this.data.contList1.forEach((item1) => {
if (item.learnType === item1.learnType) {
item.titleVal = item1.titleVal;
item.url = item1.url;
}
});
});
this.setData({
contList: list,
score: res.data.amount,
scoreNow: res.data.point
});
})
},
handleTo(e) {
const item = e.currentTarget.dataset.item;
console.log(item)
if (item.learnType == "point_login") return;
if (item.learnType == "point_read" || item.learnType == "CreditSignDone" || item.learnType == "point_comment") {
wx.switchTab({
url: item.url,
})
} else {
wx.navigateTo({
url: item.url
});
}
}
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "我的积分"
}
\ No newline at end of file
.integral-out {
width: 100%;
height: 100%;
background: linear-gradient(180deg, #d23a29 10%, #fff 50%,#f5f5f5 100%);
.integral-head {
width: 90%;
margin: 0 auto;
display: flex;
justify-content: space-between;
padding-top: 10%;
.head-item {
padding-top: 20px;
.item-score {
padding-left: 15px;
font-weight: 600;
font-size: 40px;
color: #fff;
margin-bottom: 10px;
}
.item-more {
display: flex;
align-items: center;
color: #fff;
font-size: 16px;
}
}
.head-img {
width: 42%;
}
}
.integral-box {
width: 94%;
margin: 0 auto;
border-radius: 40px;
background-color: #fff;
padding: 20px;
box-sizing: border-box;
.box-head {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.box-content {
padding: 10px 4px;
display: flex;
justify-content: space-between;
.content-items {
width: 72%;
margin-bottom: 20px;
.title {
color: #333333;
font-weight: 500;
font-size: 16px;
}
.titValue {
color: #9e9e9e;
font-size: 14px;
}
}
.btn{
height: 30px;
line-height: 30px;
padding: 4px 16px;
border-radius: 30px;
}
.active-btn {
background: linear-gradient(90deg, #d23a29, #eb6c53 100%);
color: #fff;
}
.unactive-btn {
background-color: rgba(158, 158, 158, 0.1);
color: #999999;
}
}
}
}
<view class="integral-out">
<view class="integral-head">
<view class="head-item">
<view class="item-score">{{score}}</view>
<view class="item-more">
<image src="/static/myIntegral/shop-icon.png" style="width: 48px;height: 48px;"></image>
<view>
积分商城 <text style="font-size: 14px;">(建设中)</text>
</view>
</view>
</view>
<view class="head-img">
<image src="/static/myIntegral/gift.png" style="width: 100%;height: 160px;"></image>
</view>
</view>
<view class="integral-box">
<view class="box-head">
<view style="display: flex; align-items: center;">
<image src="/static/myIntegral/jinbi.png" style="width: 40px;height: 40px; margin-right: 10px;"></image>
<view style="color: #333; font-weight: 600; font-size: 18px;">
积分规则
</view>
</view>
<view style="color: #9E9E9E; font-size: 16px;">
今日已累计 <text style="color: #E6624A;">{{scoreNow}}</text> 积分
</view>
</view>
<block wx:for="{{contList}}" data-index="{{index}}" wx:key="index">
<view class="box-content">
<view class="content-items">
<view class="title">{{item.learnName}}</view>
<view class="titValue">{{item.titleVal}}</view>
</view>
<view wx:if="{{item.flag == '1'}}" class="btn unactive-btn">已完成</view>
<view wx:else class="btn active-btn" bindtap="handleTo" data-item="{{item}}">
去完成
</view>
</view>
</block>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig';
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
infoData: {},
imageList: [],
headPortrait: "",
fullName: "",
fullNameCanChange: false,
mobile: "",
mobileCanChange: false,
description: "",
descriptionCanChange: false
},
onLoad() {
get(url.userInfoApi).then(res => {
this.setData({
infoData: res.data,
headPortrait: res.data.headPortrait,
fullName: res.data.fullName,
mobile: res.data.mobile,
description: res.data.description,
})
})
},
chooseImage() {
wx.chooseImage({
count: 1,
success: (res) => {
const tempFilePaths = res.tempFilePaths;
const TOKEN_KEY = 'auth_token';
const tokenData = wx.getStorageSync(TOKEN_KEY);
wx.uploadFile({
url: 'https://hqjddj.shanghaiairport.com/aliyun/api/upload/?companyCode=zhdj&siteCode=edu', // 服务器接口地址
filePath: tempFilePaths[0], // 单张图片路径
name: 'file', // 后台接收的字段名
header: {
'content-type': 'application/json', // 默认JSON格式
'Authorization': tokenData.token,
},
success: (res) => {
const data = JSON.parse(res.data); // 解析服务器响应
this.setData({
headPortrait: data.data,
});
},
});
}
});
console.log(this.data.headPortrait)
},
getMeInfoChange(e) {
this.setData({
fullName: e.detail.value
})
},
getMeInfoChange1(e) {
this.setData({
mobile: e.detail.value
})
},
getMeInfoChange2(e) {
this.setData({
description: e.detail.value
})
},
nameChange() {
this.setData({
fullNameCanChange: true
})
},
nameChange() {
this.setData({
fullNameCanChange: true
})
},
nameChange() {
this.setData({
fullNameCanChange: true
})
},
mobileChange() {
this.setData({
mobileCanChange: true
})
},
descriptionChange() {
this.setData({
descriptionCanChange: true
})
},
submitChange() {
let params = {
id: this.data.infoData.id,
headPortrait: this.data.headPortrait,
fullName: this.data.fullName,
mobile: this.data.mobile,
description: this.data.description,
};
// 模拟提交数据,实际使用 wx.request 替换
post(url.saveUserInfoApi, params).then(() => {
wx.showToast({
title: '保存成功',
success: () => {
wx.navigateBack()
}
})
})
},
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "个人信息"
}
\ No newline at end of file
.new-me-list-container {
width: 96%;
margin: 0 auto;
padding: 20px;
box-sizing: border-box;
.new-me-list-info {
.new-me-list-img {
display: flex;
justify-content: space-between;
align-items: center;
position: relative;
.user-img{
width: 45px;
height: 45px;
border-radius: 50%;
}
.to-info{
width: 20px;
height: 20px;
margin-left: 10px;
}
}
.me-info-item {
display: flex;
justify-content: space-between;
width: 100%;
border-bottom: 2px solid #eee;
margin: 20px 0;
.me-info-title {
font-size: 18px;
color: #000;
}
.me-info-text {
color: #000;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.only-click-icon {
width: 32px;
float: right;
color: #7c7c7c;
}
}
.me-info-desc-item {
width: 100%;
.me-info-header {
height: 40px;
line-height: 40px;
color: #000;
width: 100%;
}
.am-list-item {
padding-left: 0;
}
.am-textarea-control {
padding-bottom: 0.5rem;
textarea {
font-size: 14px;
color: #9b9b9b;
}
}
}
}
.save-btn {
margin-top: 20px;
width: 100%;
height: 40px;
line-height: 40px;
font-size: 18px;
background-color: #4285f4;
border: 1px solid #4285f4;
border-radius: 10px;
text-align: center;
color: #fff;
}
}
\ No newline at end of file
<view class="new-me-list-container">
<view class="new-me-list-info">
<view class="new-me-list-img">
<view>头像</view>
<view style="display: flex;align-items: center;">
<view style="display: flex;">
<view wx:if="{{headPortrait}}">
<image src="{{headPortrait}}" mode="aspectFill" class="user-img" bind:tap="previewImage"></image>
</view>
</view>
<view class="to-info" bind:tap="chooseImage">
<image src="/static/tomore.png" mode="aspectFill" style="width: 100%;height: 100%;" />
</view>
</view>
</view>
<view class="me-info-item">
<view class="me-info-title">姓名</view>
<input wx:if="{{fullNameCanChange}}" value="{{fullName}}" bindinput="getMeInfoChange" data-type="姓名" />
<view wx:else class="me-info-text" bind:tap="nameChange">{{fullName}}</view>
</view>
<view class="me-info-item">
<view class="me-info-title">公司</view>
<view class="me-info-text">{{infoData.companyName}}</view>
</view>
<view class="me-info-item">
<view class="me-info-title">手机号</view>
<input wx:if="{{mobileCanChange}}" value="{{mobile}}" bindinput="getMeInfoChange1" data-type="手机号" />
<view wx:else class="me-info-text" bind:tap="mobileChange">{{mobile}}</view>
</view>
<view class="me-info-desc-item">
<view class="me-info-header">个人介绍</view>
<textarea wx:if="{{descriptionCanChange}}" value="{{description}}" bindinput="getMeInfoChange2" data-type="个人介绍" />
<view wx:else bind:tap="descriptionChange">{{description}}</view>
</view>
</view>
<view class="save-btn" bindtap="submitChange">
保存
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
Page({
data: {
answerShow: false,
researchId: '',
questionData: {},
answerQuestionData:{},
answerArr: []
},
onLoad: function (options) {
this.setData({
researchId: options.id
})
let params = {
researchId: this.data.researchId
}
this.getData(params);
},
/**
* 获取问卷数据 同时也可以提交答案
*
*/
getData(params) {
post(url.getQuestionnaireDataApi, params).then(res => {
if (res.data == 1) {
get(url.getAnswerApi, {
researchId: this.data.researchId
}).then(res => {
this.setData({
answerShow: true,
answerArr: res.data.answerQuestions,
})
})
} else {
this.setData({
questionData: res.data.question,
answerQuestionData: res.data.answerQuestionVo,
type: res.data.question?.type,
answerShow: false
})
if (
params.answerQuestionVo?.isLast == 1
) {
wx.navigateBack()
}
}
})
},
//上一题
pageChangeUp() {
let params = {
researchId: this.data.researchId,
num: this.data.questionData.no - 1,
answerQuestionVo: {
questionId: this.data.questionData.id,
},
};
this.getData(params);
},
//下一题
pageChangeNext() {
//单选组件数据
const singleData = this.selectComponent('#single')?.data;
//多选组件数据
const multipleData = this.selectComponent('#multiple')?.data;
//打分组件数据
const scoringData = this.selectComponent('#scoring')?.data;
//问答组件数据
const essayData = this.selectComponent('#essay')?.data;
let params = {
researchId: this.data.researchId,
answerQuestionVo: {
questionId: this.data.questionData.id,
questionItems: [],
},
};
switch (this.data.questionData.type) {
case 1:
// 单选
params.answerQuestionVo.questionItems.push({
content: "",
optionId: singleData.singleVal,
score: "",
})
break;
case 2:
// 多选
multipleData.multipleVal.map((item) => {
params.answerQuestionVo.questionItems.push({
content: "",
optionId: item,
score: "",
})
})
break;
case 3:
// 问答
params.answerQuestionVo.questionItems.push({
content: essayData.essayVal,
optionId: "",
score: "",
})
this.selectComponent('#essay').triggerCustomEvent('');
break;
case 4:
// 打分
params.answerQuestionVo.questionItems.push({
content: "",
optionId: this.data.questionData.options[0].id,
score: scoringData.scoringVal,
})
break;
default:
break;
}
if (this.data.questionData.isLast == 1) {
params.answerQuestionVo.isLast = 1
}
this.getData(params);
this.setData({
answerShow:true
})
},
})
\ No newline at end of file
{
"usingComponents": {
"essay-question":"/pages/components/essayQuestion/index",
"multiple-choice":"/pages/components/multipleChoice/index",
"single-choice":"/pages/components/singleChoice/index",
"scoring-question":"/pages/components/scoringQuestion/index"
},
"navigationBarTitleText": "问卷详情"
}
\ No newline at end of file
/* pages/questionnaire/index.wxss */
.question-box {
padding-top: 20px;
width: 100%;
min-height: 100vh;
background: linear-gradient(0deg, #ff9286 0%, #d23a29),
linear-gradient(180deg, rgba(255, 255, 255, 0) 59%, #f5f5f5 100%),
linear-gradient(0deg, rgba(210, 58, 41, 0) 0%, #d23a29);
.question-out {
width: 92%;
margin: 0 auto;
border-radius: 12px;
padding: 20px;
background-color: #fff;
box-sizing: border-box;
.handle-btn {
margin-top: 15px;
display: flex;
justify-content: flex-end;
align-items: center;
.btn-item {
font-size: 14px;
padding: 4px 8px;
color: #fff;
background-color: #EB6C53;
border: 1PX solid #EB6C53;
box-sizing: border-box;
border-radius: 6px;
margin-left: 10px;
}
}
}
.weui-cell {
display: flex;
align-items: center;
margin-bottom: 20px;
}
}
.answer-type{
color: #67512c;
margin-right: 8px;
}
.answer-title{
color: #030303;
}
.answer-input{
width: 100%;
min-height: 30px;
line-height: 30px;
border: 1px solid #999;
padding-left: 8px;
border-radius: 5px;
}
\ No newline at end of file
<!--问卷调查-->
<view class="question-box">
<view wx:if="{{answerShow}}" class="question-out">
<view wx:for="{{answerArr}}" wx:key="id">
<view style="margin-bottom: 28px;">
<view style="margin-bottom: 15px;">
<text>{{index+1}}.</text>
<text class="answer-type">{{item.type==1?"单选题":item.type==2?"多选题":item.type==3?"问答题":"打分题"}}</text>
<text class="answer-title">{{item.content}}</text>
</view>
<radio-group wx:if="{{item.type==1}}">
<label class="weui-cell" wx:for="{{item.options}}" wx:key="id">
<view class="weui-cell__hd">
<radio value="{{item.id}}" disabled checked="{{item.answerChecked}}" />
</view>
<view class="weui-cell__bd">{{item.content}}</view>
</label>
</radio-group>
<checkbox-group wx:if="{{item.type==2}}">
<label class="weui-cell weui-check__label" wx:for="{{item.options}}" wx:key="id">
<view class="weui-cell__hd">
<checkbox value="{{item.id}}" disabled checked="{{item.answerChecked}}" />
</view>
<view class="weui-cell__bd">{{item.content}}</view>
</label>
</checkbox-group>
<input class="answer-input" wx:if="{{item.type==3}}" type="text" disabled value="{{item.answerContent}}" />
<view wx:if="{{item.type==4}}" style="display: flex;">
<text>分数:</text>
<slider disabled value="{{item.options[0].answerScore}}" min="0" max="10" show-value />
<input type="text" disabled value="{{item.options[0].answerScore}}" />
</view>
</view>
</view>
</view>
<view wx:else class="question-out">
<!-- type:1:单选题,2:多选题,3:问答题,4:打分题 -->
<single-choice wx:if="{{type == 1}}" questionData="{{questionData}}" answerQuestionData="{{answerQuestionData}}" id="single"></single-choice>
<multiple-choice wx:if="{{type == 2}}" questionData="{{questionData}}" answerQuestionData="{{answerQuestionData}}" id="multiple"></multiple-choice>
<essay-question wx:if="{{type == 3}}" questionData="{{questionData}}" answerQuestionData="{{answerQuestionData}}" id="essay"></essay-question>
<scoring-question wx:if="{{type == 4}}" questionData="{{questionData}}" answerQuestionData="{{answerQuestionData}}" id="scoring"></scoring-question>
<view class="handle-btn">
<view wx:if="{{questionData.no!=1}}" class="btn-item" bind:tap="pageChangeUp">上一题</view>
<view wx:if="{{questionData.isLast!=1}}" class="btn-item" bind:tap="pageChangeNext">下一题</view>
<view wx:if="{{questionData.isLast==1}}" class="btn-item" bind:tap="pageChangeNext">提交</view>
</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
resultShow: true,
searchHistoryList: [],
searchAllList: [],
searchResultList: [],
searchWord: '',
},
onLoad() {
// 获取历史搜索和全部搜索列表
get(url.searchHistoryApi, '').then(res => {
this.setData({
searchHistoryList: res.data
})
})
get(url.searchListAllApi, '').then(res => {
this.setData({
searchAllList: res.data,
});
})
},
onChange(e) {
this.setData({
searchWord: e.detail.value
});
},
onSubmit(e) {
const value = e.detail.value;
const value1 = e.currentTarget?.dataset?.value;
get(url.searchApi, {
searchName: value ? value : value1
}).then(res => {
let list = res.data.classificationVOList;
list.map(item => {
item.informationVoList.map(item1 => {
item1.releaseTime = moment(item1.releaseTime).format("YYYY-MM-DD")
})
})
this.setData({
searchResultList: res.data.classificationVOList,
resultShow: false,
});
})
},
onCancel() {
this.setData({
resultShow: true
});
},
newsItemClick(e) {
let item = e.currentTarget.dataset.item;
wx.navigateTo({
url: '/pages/NewsMessage/news/index?id=' + item.id,
})
},
});
\ No newline at end of file
{
"usingComponents": {}
}
\ No newline at end of file
.global-search-container {
.global-search-input {
background: linear-gradient(270deg, #ee4e3c 0%, #d23a29);
padding: 15px 0;
padding-left: 20px;
.search-input{
color: #fff;
height: 28px;
line-height: 28px;
width: 75%;
border: 1px solid #fff;
border-radius: 16px;
padding-left: 8px;
}
}
.global-search-history {
padding-left: 20px;
.global-search-history-tit {
font-size: 18px;
color: #333333;
font-weight: 600;
margin: 20px 0;
}
.global-search-history-con {
display: flex;
flex-wrap: wrap;
.global-search-history-con-item {
width: fit-content;
padding: 5px 8px;
color: #666666;
border: 1px solid #dcdee0;
font-size: 16px;
margin-right: 15px;
margin-bottom: 15px;
border-radius: 4px;
}
.global-search-history-con-item1 {
width: fit-content;
padding: 5px 8px;
color: #e6624a;
background: rgba(253, 63, 52, 0.1);
font-size: 16px;
margin-right: 15px;
margin-bottom: 15px;
border-radius: 4px;
}
}
}
.global-search-result {
padding-left: 20px;
padding-top: 20px;
.global-search-result-con {
.result-tit {
color: #000000;
font-weight: 600;
margin-bottom: 30px;
span {
display: inline-block;
width: 8px;
height: 15px;
background: linear-gradient(180deg, #fe742b, #fc5b2b 100%);
border-radius: 10px;
margin-right: 4px;
}
}
.result-content {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
.result-content-img{
width: 40%;
}
.result-content-item {
width: 58%;
height: 100px;
display: flex;
flex-direction: column;
justify-content: space-between;
.result-content-item-tit {
padding-right: 15px;
color: #000;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
/* 定义文本的行数 */
overflow: hidden;
text-overflow: ellipsis;
}
.result-content-item-bot {
font-size: 14px;
color: #ABABAB;
span {
margin-right: 10px;
}
}
}
}
}
}
}
\ No newline at end of file
<view class="global-search-container">
<view class="global-search-input">
<view style="width: 95%; display: flex; justify-content: space-between; align-items: center;">
<input placeholder="搜索" bindinput="onChange" bindconfirm="onSubmit" maxlength="8"
placeholder-style="color:#fff;" class="search-input"/>
<view style="text-align:center;width: 18%; color: #fff;font-size: 18px; font-weight: 600;" bindtap="onCancel">
取消
</view>
</view>
</view>
<block wx:if="{{resultShow}}">
<view class="global-search-history">
<view class="global-search-history-tit">历史搜索</view>
<view class="global-search-history-con">
<view class="global-search-history-con-item" wx:for="{{searchHistoryList}}" wx:key="id" bindtap="onSubmit" data-value="{{item.cnName}}">
{{item.cnName}}
</view>
</view>
<view class="global-search-history-tit">大家都在搜</view>
<view class="global-search-history-con">
<view class="global-search-history-con-item1" wx:for="{{searchAllList}}" wx:key="id" bindtap="onSubmit" data-value="{{item.cnName}}">
{{item.cnName}}
</view>
</view>
</view>
</block>
<block wx:else>
<view class="global-search-result">
<view class="global-search-result-con" wx:for="{{searchResultList}}" wx:key="id">
<view class="result-tit">
<span></span> {{item.name}}
</view>
<view class="result-content" wx:for="{{item.informationVoList}}" wx:key="id" bindtap="newsItemClick" data-item="{{item}}">
<view class="result-content-img">
<image src="{{item.logoPath}}" style="width:100%; height: 100px;" mode="aspectFill" />
</view>
<view class="result-content-item">
<view class="result-content-item-tit">
{{item.fileName}}
</view>
<view class="result-content-item-bot">
<span>{{item.author}}</span>
{{item.releaseTime}}
</view>
</view>
</view>
</view>
</view>
</block>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
dataList: {},
btnType: 0,
},
onLoad: function (options) {
let params = {
examId: options.id
}
post(url.getExamDetatilApi, params).then(res => {
let item = res.data;
this.getBtnStatu(item)
item.startTime = moment(item.startTime).format("YYYY-MM-DD");
item.endTime = moment(item.endTime).format("YYYY-MM-DD");
this.setData({
dataList: item,
});
})
},
getBtnStatu(item) {
let itemTime = new Date().getTime();
// btnType 0:没有考试次数,1:考试时间未到,2:考试已过时,3:继续考试,4:开始考试
if (
Number.parseInt(item.answerNum) !== 0 &&
Number.parseInt(item.examNum) >= Number.parseInt(item.answerNum)
) {
this.setData({
btnType: 0
})
} else if (itemTime < item.startTime || itemTime > item.endTime) {
if (itemTime < item.startTime) {
this.setData({
btnType: 1
})
} else {
this.setData({
btnType: 2
})
}
} else {
if (String(item.isExam) === "1") {
this.setData({
btnType: 3
})
} else {
this.setData({
btnType: 4
})
}
}
},
lookHistory() {
wx.navigateTo({
url: '/pages/trainingAndTest/examHistory/index?id='+this.options.id+`&type=`+this.data.btnType,
})
},
startClick() {
// let {
// id,
// isExam,
// answerId,
// trainingProjectId,
// pageMode
// } =
// this.state.dataList;
if (this.data.btnType >= 3) {
wx.navigateTo({
url: '/pages/trainingAndTest/examQuestion/index?id='+this.options.id,
})
}
},
})
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "考试详情"
}
\ No newline at end of file
.exam-of-detail {
background: linear-gradient(0deg, #ff9286 0%, #d23a29),
linear-gradient(180deg, rgba(255, 255, 255, 0) 59%, #f5f5f5 100%),
linear-gradient(0deg, rgba(210, 58, 41, 0) 0%, #d23a29);
width: 100%;
min-height: 100vh;
padding-top: 30px;
.exam-detail-name {
width: 100%;
margin-bottom: 40px;
height: 50px;
line-height: 50px;
text-align: center;
font-size: 20px;
color: #fff;
font-weight: 500;
background: linear-gradient(90deg,
rgba(255, 151, 130, 0),
#ff9782 53%,
rgba(255, 151, 130, 0) 100%);
}
.exam-detail-container {
width: 94%;
margin: 0 auto;
border-radius: 20px;
background: #fffdfa;
box-shadow: 0 -2px 17px 0 rgba(0, 0, 0, 0.08);
box-sizing: border-box;
.exam-detail-info {
width: 80%;
margin: 0 auto;
padding: 20px 10px;
border-bottom: 2px solid #e5e6e8;
display: flex;
align-items: center;
.info-tit {
width: 30%;
text-align: justify;
text-align-last: justify;
margin-right: 30px;
}
}
}
.begin-btn {
width: 100%;
position: fixed;
bottom: 0;
left: 0;
.btn {
width: 100%;
height: 45px;
line-height: 45px;
color: #fff;
font-size: 18px;
text-align: center;
}
.btn-active {
background: linear-gradient(270deg, #eb6c53 0%, #d23a29);
}
.btn-nullity {
background-color: rgb(184, 183, 183);
}
}
}
\ No newline at end of file
<view class="exam-of-detail">
<view class="exam-detail-name">{{dataList.name}}</view>
<view class="exam-detail-container">
<view class="exam-detail-info">
<view class="info-tit">开始时间</view>
<view>{{dataList.startTime}}</view>
</view>
<view class="exam-detail-info">
<view class="info-tit">结束时间</view>
<view>{{dataList.endTime}}</view>
</view>
<view class="exam-detail-info">
<view class="info-tit">题数</view>
<view>{{dataList.sumQuestion}} 题</view>
</view>
<view class="exam-detail-info">
<view class="info-tit">总分</view>
<view>{{dataList.score || 100}} 分</view>
</view>
<view class="exam-detail-info">
<view class="info-tit">及格分</view>
<view>{{dataList.qualifiedScore}} 分</view>
</view>
<view class="exam-detail-info">
<view class="info-tit">考试时长</view>
<view>{{dataList.duration}} 分钟</view>
</view>
<view class="exam-detail-info">
<view class="info-tit">考试次数</view>
<view>{{dataList.examNum}} / {{dataList.answerNum == 0?'无限次':dataList.answerNum}}</view>
<view wx:if="{{dataList.examNum >0}}" style="display: flex;margin-left: auto;color: rgb(66, 133, 244);" bind:tap="lookHistory">查看历史</view>
</view>
<view class="exam-detail-info" style="display: block;">
<view class="info-tit" style="margin-bottom: 20px;">考试说明</view>
<view style="text-indent: 2em;">{{dataList.description ? dataList.description : "暂无信息"}}</view>
</view>
</view>
<view class="begin-btn">
<view bind:tap="startClick" class="btn {{btnType>=3?'btn-active':'btn-nullity'}}">{{btnType == 0?'没有考试次数':btnType == 1?'考试时间未到':btnType == 2?'考试已过时':btnType == 3?'继续考试':'开始考试'}}</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
finishData: {},
examStu:0
},
onLoad: function (options) {
get(url.getExamHistoryListApi, {
examId: options.id
}).then(res => {
let item = res.data;
item.hisList.map(item => {
item.submitTime = moment(item.submitTime).format("YYYY-MM-DD HH:mm:ss");
})
this.setData({
finishData: item,
examStu:options.type
});
})
},
handleExamDetail() {
if (this.data.examStu >= 3) {
wx.navigateTo({
url: '/pages/trainingAndTest/examDetail/index?id=' + this.options.id,
})
}
},
})
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "测试历史"
}
\ No newline at end of file
/* 考试结果容器 */
.exam-result {
background-color: #f5f5f5;
.result-detail {
padding: 20px;
}
/* 结果详情卡片 */
.detail-card {
border-radius: 10px;
text-align: center;
/* 分数显示样式 */
.score {
color: blue;
font-size: 24px;
}
.score-red {
color: #f00;
font-size: 24px;
}
}
/* 历史列表样式 */
.history-list {
background-color: #fff;
border-radius: 10px;
padding: 20px;
.list-header {
font-size: 18px;
font-weight: bold;
margin-bottom: 10px;
}
.list-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px 0;
border-bottom: 1px solid #eee;
}
.yes {
color: #0f0;
}
.no {
color: #f00;
}
}
}
\ No newline at end of file
<view class="exam-result">
<!-- 结果详情 -->
<view class="result-detail">
<view class="detail-card">
<view style="font-size: 18px;font-weight: bold;margin-bottom: 20px;">{{finishData.examName}}</view>
<!-- 根据不同状态显示不同信息 -->
<view wx:if="{{finishData.isres == 0}}">
<view wx:if="{{finishData.isScore == 0}}">{{"本场考试成绩不显示"}}</view>
<view wx:elif="{{finishData.isScore == 2}}">{{"本场考试后显示成绩"}}</view>
<view wx:else>
<text class="{{finishData.score < finishData.scoreSuccess ? 'score-red' : 'score'}}">
<text class="score-font">{{finishData.score}}</text>分
</text>
<image class="score-img" src="/static/exam/underline.png" mode="aspectFit" style="width: 40px;height: 25px;"></image>
</view>
</view>
<view wx:else>{{"批阅中"}}</view>
<!-- 显示评语 -->
<view wx:if="{{finishData.remark != '' && finishData.isres == 0}}">
<image src="/static/exam/message.png" style="width: 50px;height: 50px;" mode="aspectFill"></image>
<text>{{finishData.remark}}</text>
</view>
</view>
<!-- 按钮区域 -->
<view>
<!-- 再考一次按钮 -->
<button disabled="{{examStu<3}}" bindtap="handleExamDetail" wx:if="{{finishData.answerNum == 0 || finishData.examNumAll <= finishData.answerNum}}">再考一次</button>
</view>
</view>
<!-- 考试历史列表 -->
<view wx:if="{{finishData.hisList.length > 0}}" class="history-list">
<view class="history-box">
<view class="list-header">
<text>考试历史({{finishData.hisList.length}})</text>
</view>
<view wx:for="{{finishData.hisList}}" wx:key="index" class="list-item" bindtap="itemClick" data-item="{{item}}" data-islookanswer="{{finishData.isLookAnswer}}">
<view style="display: flex;">
<text style="width: 15px;text-align: center;margin-right: 10px;">{{index + 1}} </text>
<text>{{item.submitTime}}</text>
</view>
<view class="{{item.isres == 0 ? (item.score < item.qualifiedScore ? 'no' : 'yes') : 'yes'}}">
<view style="width: 90px;" wx:if="{{finishData.isScore == 1}}">
<text>{{item.score < item.qualifiedScore ? '未通过' : '已通过'}}</text>
<text style="width: 36px;margin-left: 3px;">{{item.score}}分</text>
</view>
<text wx:else>{{"批阅中"}}</text>
</view>
</view>
</view>
</view>
<view wx:else>{{"暂无数据"}}</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
questionData: {},
btnType: 0,
answerId: '',
accountId: '',
pageNo: 1,
questionNumber: 0,
questionItems: [],
radioVal: ""
},
onLoad: function (options) {
console.log(options)
let params = {
examId: options.id,
pageNo: 1,
pageSize: 1
}
this.getQuestionItem(params)
},
getQuestionItem(params) {
post(url.getQuestionItemApi, params).then(res => {
let item = res.data;
item.questions[0].index = Number(item.questions[0].index)
this.setData({
questionData: item.questions[0],
answerId: item.answerId,
accountId: item.accountId,
questionNumber: item.questionNumber
});
})
},
beforeQuestion() {
this.setData({
pageNo: this.data.pageNo - 1
})
let params = {
examId: this.options.id,
answerId: this.data.answerId,
pageNo: this.data.pageNo,
pageSize: 1
}
this.getQuestionItem(params)
},
nextQuestion() {
this.setData({
pageNo: this.data.pageNo + 1
})
this.saveQuestionItem()
},
saveQuestionItem() {
const itemData = this.selectComponent('#examItem')?.data;
this.setData({
radioVal: itemData.radioVal
})
console.log(itemData.radioVal)
// 选项为空的时候,判断之前是不是有过答案,如果有就保存之前的答案
let ops = []
if (!itemData.radioVal) {
this.data.questionData.questionOptions.map(item => {
if (item.answer == 1) {
ops.push({
answer: item.answer,
optionId: item.optionId,
sort: item.sort
})
} else {
if (item.optionId == this.data.radioVal) {
ops.push({
answer: 1,
optionId: item.optionId,
sort: item.sort
})
} else {
ops.push({
answer: 0,
optionId: item.optionId,
sort: item.sort
})
}
}
})
} else {
this.data.questionData.questionOptions.map(item => {
if (this.data.questionData.type == 1) {
if (item.optionId == this.data.radioVal) {
ops.push({
answer: 1,
optionId: item.optionId,
sort: item.sort
})
} else {
ops.push({
answer: 0,
optionId: item.optionId,
sort: item.sort
})
}
}
})
}
this.data.questionItems.push({
ansQId: this.data.questionData.answerQuestionId,
mark: this.data.questionData.flag,
ops: ops,
sub: this.data.questionData.sub,
type: this.data.questionData.type
})
let params = {
accountId: this.data.accountId,
examId: this.options.id,
answerId: this.data.answerId,
epList: this.data.questionItems
}
post(url.saveQuestionItemApi, params).then(res => {
let params = {
examId: this.options.id,
answerId: this.data.answerId,
pageNo: this.data.pageNo,
pageSize: 1
}
this.getQuestionItem(params)
})
},
})
\ No newline at end of file
{
"usingComponents": {
"question-item":"/pages/components/questionItem/index"
},
"navigationBarTitleText": "测试问题"
}
\ No newline at end of file
.question-out{
width: 100%;
min-height:100vh;
background-color: #f5f5f5;
.question-btn{
position: fixed;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
background-color: #fff;
display: flex;
align-items: center;
justify-content: flex-end;
.btn{
width: 80px;
height: 35px;
line-height: 35px;
text-align: center;
background-color: #4285f4;
font-size: 16px;
color: #fff;
border-radius: 6px;
margin-right: 8px;
}
}
}
\ No newline at end of file
<view class="question-out">
<view>
<question-item id="examItem" questionData="{{questionData}}"></question-item>
</view>
<view class="question-btn">
<view wx:if="{{pageNo>1}}" class="btn" bind:tap="beforeQuestion">上一题</view>
<view wx:if="{{pageNo!=questionNumber}}" class="btn" bind:tap="nextQuestion">下一题</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
dataList: {},
btnType: 0,
},
onLoad: function (options) {
let params = {
examId: options.id
}
post(url.getExamDetatilApi, params).then(res => {
let item = res.data;
item.startTime = moment(item.startTime).format("YYYY-MM-DD");
this.setData({
dataList: item,
});
})
},
})
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "测试结果"
}
\ No newline at end of file
/* pages/trainingAndTest/examResult/index.wxss */
\ No newline at end of file
<!--pages/trainingAndTest/examResult/index.wxml-->
<text>pages/trainingAndTest/examResult/index.wxml</text>
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
navSta: true,
newsList: [],
examList: [],
},
onLoad: function (options) {
if(options.type == 2){
this.setData({
navSta:false
})
}else{
this.setData({
navSta:true
})
}
let params = {
pageNo: 1,
pageSize: 50,
relationId: options.id,
terminalName: "MOBILE",
typeName: "news",
}
//培训列表
post(url.getTrainingListApi, params).then(res => {
res.data.news.map((item) => {
item.releaseTime = moment(item.releaseTime).format("YYYY-MM-DD")
})
this.setData({
newsList: res.data.news
})
})
//测试列表
post(url.getExamListApi, {
pageNo: 1,
pageSize: 50
}).then(res => {
res.data.map((item) => {
item.startTime = moment(item.startTime).format("YYYY-MM-DD");
item.endTime = moment(item.endTime).format("YYYY-MM-DD");
})
this.setData({
examList: res.data
})
})
},
navChange() {
let sta = this.data.navSta
this.setData({
navSta: !sta
})
},
handleTo: function (e) {
let item = e.currentTarget.dataset.item;
wx.navigateTo({
url: '/pages/NewsMessage/news/index?id='+item.id,
})
},
handleExamDetail: function (e) {
let item = e.currentTarget.dataset.item;
wx.navigateTo({
url: '/pages/trainingAndTest/examDetail/index?id='+item.id,
})
},
})
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "培训测试"
}
\ No newline at end of file
.out {
.nav-out {
width: 100%;
height: 45px;
display: flex;
background: linear-gradient(270deg, #ee4e3c 0%, #d23a29);
padding-bottom: 4px;
transition: .5s;
margin-bottom: 20px;
.nav-item {
width: 50%;
height: 42px;
line-height: 42px;
color: #fff;
text-align: center;
}
.active {
font-size: 18px;
border-bottom: 4px solid #fff;
}
}
}
//培训测试
.training-out{
width: 96%;
margin: 0 auto;
.new-list {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
}
.new-font {
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
word-break: break-all;
}
.new-item {
width: 60%;
height: 95px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
.exam-statu-icon {
width: 80px;
height: 30px;
line-height: 30px;
padding: 0px;
text-align: center;
border-radius: 45px;
}
.exam-statu-icon0 {
background: rgba(253, 63, 52, 0.05);
border: 1px solid #f3ab9f;
color: #e6624a;
}
.exam-statu-icon1 {
background: linear-gradient(90deg, #ff8058, #ffb865 100%);
color: #fff;
}
.exam-statu-icon2 {
background: #cbeecd;
border: 1px solid #cbeecd;
color: #53af5c;
}
.exam-score {
margin-left: 5px;
font-size: 18px;
color: #53AF5C;
}
.exam-score1 {
margin-left: 5px;
font-size: 18px;
color: #FC7A43;
}
\ No newline at end of file
<view class="out">
<view class="nav-out">
<view class="nav-item {{navSta?'active':''}}" bind:tap="navChange">培训</view>
<view class="nav-item {{!navSta?'active':''}}" bind:tap="navChange">测试</view>
</view>
<view wx:if="{{navSta}}" class="training-out">
<view class="new-out">
<block wx:for="{{ newsList }}" wx:key="id" wx:for-index="index">
<view class="new-list" bindtap="handleTo" data-item="{{ item }}">
<image style="width: 36%;height:100px;" src="{{item.logoPath}}" mode="scaleToFill" />
<view class="new-item">
<view class="new-font">{{item.fileName}}</view>
<view style="color: #999;font-size: 14px;">
{{item.releaseTime}}
</view>
</view>
</view>
</block>
</view>
</view>
<view wx:else class="training-out">
<block wx:for="{{ examList }}" wx:key="id" wx:for-index="index">
<view class="new-list" bindtap="handleExamDetail" data-item="{{item}}">
<image style="width: 36%;height:100px;" src="{{item.logoImg}}" mode="scaleToFill" />
<view class="new-item">
<view class="new-font">{{item.name}}</view>
<view style="display: flex;">
<view class="exam-statu-icon {{ item.handle == 0? 'exam-statu-icon0': item.handle == 5? 'exam-statu-icon1': 'exam-statu-icon2'}}">
{{item.handle == 0
? "开始考试"
: item.handle == 5
? "待补考"
: "已完成"}}
</view>
<view class="{{item.score > 60 ? 'exam-score' : 'exam-score1'}}">
<text>{{item.score ? item.score : ""}}</text>
<text>{{item.score ? "分" : ""}}</text>
</view>
</view>
<view style="color: #999;font-size: 14px;">
{{item.startTime}}-{{item.endTime}}
</view>
</view>
</view>
</block>
</view>
</view>
\ No newline at end of file
Page({
data: {
content: '',
keywords: '',
name: '',
img: ''
},
onLoad(options) {
const imgSrc = wx.getStorageSync('voteDetailImgSrc');
console.log(options)
this.setData({
content: options.content,
keywords: options.keywords,
name: options.name,
img: imgSrc
});
}
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "投票详情"
}
\ No newline at end of file
//详情
.vote-out{
padding-top: 20px;
padding-bottom: 40px;
width: 100%;
min-height: 100vh;
background: linear-gradient(0deg, #ff9286 0%, #d23a29),
linear-gradient(180deg, rgba(255, 255, 255, 0) 59%, #f5f5f5 100%),
linear-gradient(0deg, rgba(210, 58, 41, 0) 0%, #d23a29);
}
.detail-box {
width: 90%;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border-radius: 20px;
box-sizing: border-box;
.detail-name {
font-size: 18px;
color: #353535;
font-weight: 600;
display: flex;
align-items: center;
}
.detail-img {
margin-top: 10px;
}
.detail-content {
text-indent: 2em;
background-color: #f7f7f7;
padding: 10px;
color: #333;
font-size: 16px;
line-height: 60px;
border-radius: 20px;
transform: translateY(-20px);
}
}
\ No newline at end of file
<view class="vote-out">
<view class="detail-box">
<view class="detail-name">
<view
class="{{keywords == '精石之美' ? 'cont-icon1' : keywords == '突破之美' ? 'cont-icon2' : keywords == '进取之美' ? 'cont-icon3' : 'cont-icon4'}}"
>
{{keywords}}
</view>
{{name}}
</view>
<view class="detail-img">
<image src="{{img}}" mode="aspectFill" style="width: 100%;height: 260px;"></image>
</view>
<view class="detail-content">{{content}}</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
const moment = require('/miniprogram_npm/moment/index.js');
Page({
data: {
list: [],
oldVoteNum: '',
voteNum: '',
name: ''
},
onLoad(options) {
const id = options.id;
get(url.voteListApi, {
researchId: id
}).then(res => {
const list = res.data.map((item) => {
item.actived = true;
return item;
});
this.setData({
list: list
});
})
get(url.voteSumbitSecondApi, {
researchId: id
}).then(res => {
this.setData({
voteNum: res.data.voteNum,
oldVoteNum: res.data.voteNum,
name: res.data.name,
});
})
},
handleTo(e) {
let item = e.currentTarget.dataset.item;
wx.setStorageSync('voteDetailImgSrc', item.contentAppendixUrl);
wx.navigateTo({
url: `/pages/vote/detail/index?id=${this.options.id}&content=${item.content}&keywords=${item.keywords}&name=${item.options[0].content}`
});
},
handleVote(e) {
let item = e.currentTarget.dataset.item;
if (this.data.oldVoteNum !== 0) {
if (this.data.voteNum === 0) {
wx.showModal({
title: '提示',
showCancel: false,
content: '本次投票最多选择' + this.data.oldVoteNum + '项',
})
} else {
if (item.actived) {
this.setData({
voteNum: this.data.voteNum - 1
});
const newList = this.data.list.map((i) => {
if (i.id == item.id) {
i.actived = false;
}
return i;
});
this.setData({
list: newList
});
console.log(this.data.list)
}
}
}
},
handleSumbit(voteNum, oldVoteNum) {
if (this.data.oldVoteNum === 0) {
wx.navigateTo({
url: `/pages/vote/theCharts/index?id=${this.options.id}`
});
} else {
const xkeyData = [];
const {
list
} = this.data;
list.forEach((item) => {
if (item.actived) {
xkeyData.push({
questionId: item.options[0].questionId,
questionType: item.options[0].questionType,
questionItems: [{
optionId: '',
content: '',
score: ''
}]
});
} else {
xkeyData.push({
questionId: item.options[0].questionId,
questionType: item.options[0].questionType,
questionItems: [{
optionId: item.options[0].id,
content: '',
score: ''
}]
});
}
});
const params = {
researchId: this.options.id,
terminalType: 2,
startTime: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
submitTime: moment(new Date()).format("YYYY-MM-DD HH:mm:ss"),
questions: xkeyData
};
if (this.data.voteNum == this.data.oldVoteNum) {
wx.showModal({
title: '提示',
showCancel: false,
content: '本次投票最少选择1项',
})
} else {
post(url.voteSumbitApi, params).then(() => {
get(url.voteSumbitSecondApi, {
researchId: this.options.id
}).then(res => {
this.setData({
voteNum: res.data.voteNum,
oldVoteNum: res.data.voteNum
});
})
})
}
}
},
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "我要投票"
}
\ No newline at end of file
.vote-out {
padding-top: 20px;
padding-bottom: 40px;
width: 100%;
min-height: 100vh;
background: linear-gradient(0deg, #ff9286 0%, #d23a29),
linear-gradient(180deg, rgba(255, 255, 255, 0) 59%, #f5f5f5 100%),
linear-gradient(0deg, rgba(210, 58, 41, 0) 0%, #d23a29);
.vote-title {
width: 92%;
margin: 0 auto;
margin-bottom: 30px;
height: 40px;
line-height: 40px;
text-align: center;
font-size: 18px;
color: #fff;
font-weight: 500;
background: linear-gradient(
90deg,
rgba(255, 151, 130, 0),
#ff9782 53%,
rgba(255, 151, 130, 0) 100%
);
}
.vote-box {
width: 92%;
margin: 0 auto;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
padding-bottom: 40px;
.vote-top {
width: 48%;
height: 260px;
border-radius: 20px;
margin-bottom: 40px;
background-color: #fff;
overflow: hidden;
.top-img {
width: 100%;
height: 56%;
position: relative;
.index-icon {
position: absolute;
top: 0;
left: 0;
width: 34px;
height: 35px;
line-height: 35px;
text-align: center;
background: linear-gradient(136deg, #ffbf61 6%, #fe8819 100%);
border-radius: 20px 0px 20px 0px;
color: #fff;
font-size: 18px;
}
}
.top-content {
height: 44%;
display: flex;
flex-direction: column;
align-items: center;
justify-content: space-around;
.cont-name {
font-size: 16px;
color: #353535;
font-weight: 600;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
overflow: hidden;
}
}
.top-btn-select {
padding: 4px 24px;
text-align: center;
background: linear-gradient(90deg, #ff8058, #ffb865 100%);
border-radius: 40px;
color: #fff;
font-size: 18px;
}
.top-btn-selected {
padding: 4px 20px;
text-align: center;
background: #e5e6e8;
border-radius: 40px;
color: #999999;
font-size: 18px;
}
}
}
.cont-icon1 {
width: 140px;
padding: 6px 10px;
color: #e943ff;
font-size: 28px;
background-color: rgba(233, 67, 255, 0.1);
}
.cont-icon2 {
width: 140px;
padding: 4px 10px;
color: #e65858;
font-size: 28px;
background-color: rgba(230, 88, 88, 0.1);
}
.cont-icon3 {
width: 140px;
padding: 4px 10px;
color: #53af5c;
font-size: 28px;
background-color: rgba(120, 193, 127, 0.1);
}
.cont-icon4 {
width: 140px;
padding: 4px 10px;
color: #f5912a;
font-size: 28px;
background-color: rgba(255, 152, 56, 0.1);
}
.signup-modal {
.am-modal-content {
background: linear-gradient(180deg, #ffe2e2 0%, #fff 25%);
}
.am-modal-title {
color: #16181a;
font-weight: 600;
}
.modal-body {
text-align: left;
margin: 28px 0;
}
.am-modal-button {
width: 45% !important;
height: 80px !important;
line-height: 80px !important;
margin: 0 auto;
color: #fff !important;
margin-bottom: 25px;
background: linear-gradient(270deg, #eb6c53, #d23a29);
}
}
.sumbit-btn {
width: 100%;
text-align: center;
padding: 10px 0;
background: linear-gradient(270deg, #eb6c53 0%, #d23a29);
border-radius: 5px;
color: #fff;
font-size: 18px;
position: fixed;
bottom: 0px;
}
//详情
.detail-box {
width: 90%;
margin: 0 auto;
background-color: #fff;
padding: 30px;
border-radius: 30px;
.detail-name {
font-size: 40px;
color: #353535;
font-weight: 600;
display: flex;
align-items: center;
}
.detail-img {
margin-top: 10px;
img {
width: 100%;
border-radius: 20px;
}
}
.detail-content {
text-indent: 2em;
background-color: #f7f7f7;
padding: 20px;
color: #333;
font-size: 30px;
line-height: 60px;
border-radius: 20px;
transform: translateY(-20px);
}
}
//排行榜
.charts-box {
width: 90%;
margin: 0 auto;
justify-content: space-between;
.charts-top {
display: flex;
justify-content: center;
.charts {
width: 33%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.top-img {
width: 180px;
height: 180px;
transform: translateY(75px);
position: relative;
img {
width: 100%;
height: 100%;
}
.info-img1 {
position: absolute;
top: 51px;
left: 30px;
width: 150px;
height: 150px;
z-index: -1;
img {
border-radius: 50%;
}
}
.info-img2 {
position: absolute;
top: 12px;
left: 26px;
width: 130px;
height: 130px;
z-index: -1;
img {
border-radius: 50%;
}
}
}
.top-info {
width: 100%;
padding: 80px 0px;
border-radius: 20px;
text-align: center;
background: linear-gradient(0deg, #d64231 0%, #ff7060 100%);
padding-bottom: 160px;
.info-font {
font-size: 40px;
color: #fff;
}
}
}
.charts1 {
width: 35%;
transform: translateY(-60px);
}
.charts2 {
transform: translateY(-10px);
transform: translateX(15px);
}
.charts3 {
transform: translateX(-15px);
}
}
.charts-content {
background-color: #fff;
border-radius: 30px;
padding: 40px 40px;
padding-bottom: 10px;
transform: translateY(-80px);
.content-box {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #e5e6e8;
.user_info {
width: 100px;
height: 25px;
line-height: 25px;
text-align: justify; //主要对齐属性
span {
display: inline-block;
padding-left: 100%;
}
}
.score {
width: 10%;
display: flex;
color: #e86d57;
font-size: 32px;
display: flex;
align-items: center;
}
}
.content-box:last-child {
border-bottom: 0px;
}
}
}
}
<view class="vote-out">
<view class="vote-title">{{name}}</view>
<view style="width: 92%; margin: 0 auto; display: flex; justify-content: space-between; margin-bottom: 20px;">
<view style="color: rgba(255,255,255,0.6);">点击图片可查看详情</view>
<view style="color: rgba(255,255,255,1);">剩余投票次数:{{voteNum}}次</view>
</view>
<view class="vote-box">
<block wx:for="{{list}}" wx:key="index">
<view class="vote-top">
<view class="top-img" bindtap="handleTo" data-item="{{item}}">
<image src="{{item.contentAppendixUrl}}" mode="aspectFill" style="width: 100%;height: 100%;"></image>
<view class="index-icon">{{index + 1}}</view>
</view>
<view class="top-content">
<view class="cont-name">{{item.options[0].content}}</view>
<view class="{{item.keywords == '精石之美' ? 'cont-icon1' : item.keywords == '突破之美' ? 'cont-icon2' : item.keywords == '进取之美' ? 'cont-icon3' : 'cont-icon4'}}">{{item.keywords}}</view>
<view class="{{oldVoteNum != 0 && item.actived ? 'top-btn-select' : 'top-btn-selected'}}" bindtap="handleVote" data-item="{{item}}">
{{item.actived ? '投票' : '已投票'}}
</view>
</view>
</view>
</block>
</view>
<view class="sumbit-btn" bindtap="handleSumbit">
{{oldVoteNum == 0 ? '查看排名' : '提交'}}
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../../utils/request');
import url from '../../../utils/urlconfig'
Page({
data: {
list: [],
topList: []
},
onLoad(options) {
get(url.voteTopApi, {
researchId: options.id
}).then(res => {
const list = res.data.rankingList;
let keywords1 = list[0]?.keywords;
let keywords2 = list[1]?.keywords;
let keywords3 = list[2]?.keywords;
let content1 = list[0]?.content;
let content2 = list[1]?.content;
let content3 = list[2]?.content;
let topImg1 = list[0]?.contentAppendixUrl;
let topImg2 = list[1]?.contentAppendixUrl;
let topImg3 = list[2]?.contentAppendixUrl;
let topScore1 = list[0]?.voteCount;
let topScore2 = list[1]?.voteCount;
let topScore3 = list[2]?.voteCount;
let topList = list.slice(3, 9);
this.setData({
list,
topList,
keywords1,
keywords2,
keywords3,
content1,
content2,
content3,
topImg1,
topImg2,
topImg3,
topScore1,
topScore2,
topScore3
});
})
}
});
\ No newline at end of file
{
"usingComponents": {},
"navigationBarTitleText": "投票排行榜"
}
\ No newline at end of file
//排行榜
.vote-out {
padding-top: 20px;
padding-bottom: 40px;
width: 100%;
min-height: 100vh;
background: linear-gradient(0deg, #ff9286 0%, #d23a29),
linear-gradient(180deg, rgba(255, 255, 255, 0) 59%, #f5f5f5 100%),
linear-gradient(0deg, rgba(210, 58, 41, 0) 0%, #d23a29);
}
.charts-box {
width: 96%;
margin: 0 auto;
justify-content: space-between;
.charts-top {
display: flex;
justify-content: center;
.charts {
width: 33%;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
.top-img {
width: 100px;
height: 120px;
transform: translateY(55px);
position: relative;
.info-img1 {
position: absolute;
top: 16px;
left: 15px;
width: 84px;
height: 84px;
z-index: -1;
.info-img1-item {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
.info-img2 {
position: absolute;
top: 8px;
left: 6px;
width: 90px;
height: 90px;
z-index: -1;
.info-img2-item {
width: 100%;
height: 100%;
border-radius: 50%;
}
}
}
.top-info {
width: 100%;
padding: 60px 0px;
border-radius: 20px;
text-align: center;
background: linear-gradient(0deg, #d64231 0%, #ff7060 100%);
padding-bottom: 100px;
.info-font {
font-size: 18px;
color: #fff;
}
}
}
.charts1 {
width: 35%;
transform: translateY(-60px);
}
.charts2 {
transform: translateY(-10px);
transform: translateX(15px);
}
.charts3 {
transform: translateX(-15px);
}
}
.charts-content {
background-color: #fff;
border-radius: 30px;
padding: 40px 40px;
padding-bottom: 10px;
transform: translateY(-80px);
.content-box {
display: flex;
align-items: center;
justify-content: space-between;
margin-bottom: 20px;
padding-bottom: 20px;
border-bottom: 1px solid #e5e6e8;
.user_info {
width: 100px;
height: 25px;
line-height: 25px;
text-align: justify; //主要对齐属性
span {
display: inline-block;
padding-left: 100%;
}
}
.score {
width: 10%;
display: flex;
color: #e86d57;
font-size: 16px;
display: flex;
align-items: center;
}
}
.content-box:last-child {
border-bottom: 0px;
}
}
}
\ No newline at end of file
<view class="vote-out">
<view class="charts-box">
<view class="charts-top">
<view class="charts charts2">
<view class="top-img">
<image src="/static/vote/top2.png" mode="aspectFill" style="width:100%;height: 100%;"></image>
<view class="info-img2">
<image src="{{topImg2}}" mode="aspectFill" style="width:100%;height: 100%;border-radius: 50%;"></image>
</view>
</view>
<view class="top-info">
<view class="info-font">{{content2}}</view>
<view class="detail-content">
<view class="{{keywords2 == '精石之美' ? 'cont-icon1' : keywords2 == '突破之美' ? 'cont-icon2' : keywords2 == '进取之美' ? 'cont-icon3' : 'cont-icon4'}}">
{{keywords2}}
</view>
</view>
<view class="info-font">
{{topScore2}}
<text style="font-size: 16px">票</text>
</view>
</view>
</view>
<view class="charts charts1">
<view class="top-img" style="width: 120px; height: 100px">
<image src="/static/vote/top1.png" mode="aspectFill" style="width:100%;height: 100%;"></image>
<view class="info-img1">
<image class="info-img1-item" src="{{topImg1}}" mode="scaleToFill"></image>
</view>
</view>
<view class="top-info">
<view class="info-font">{{content1}}</view>
<view class="detail-content">
<view class="{{keywords1 == '精石之美' ? 'cont-icon1' : keywords1 == '突破之美' ? 'cont-icon2' : keywords1 == '进取之美' ? 'cont-icon3' : 'cont-icon4'}}">
{{keywords1}}
</view>
</view>
<view class="info-font">
{{topScore1}}
<text style="font-size: 16px">票</text>
</view>
</view>
</view>
<view class="charts charts3">
<view class="top-img">
<image src="/static/vote/top3.png" mode="aspectFill" style="width:100%;height: 100%;"></image>
<view class="info-img2">
<image class="info-img2-item" src="{{topImg3}}" mode="aspectFill"></image>
</view>
</view>
<view class="top-info">
<view class="info-font">{{content3}}</view>
<view class="detail-content">
<view class="{{keywords3 == '精石之美' ? 'cont-icon1' : keywords3 == '突破之美' ? 'cont-icon2' : keywords3 == '进取之美' ? 'cont-icon3' : 'cont-icon4'}}">
{{keywords3}}
</view>
</view>
<view class="info-font">
{{topScore3}}
<text style="font-size: 16px">票</text>
</view>
</view>
</view>
</view>
<view wx:if="{{topList.length>0}}" class="charts-content">
<block wx:for="{{topList}}" wx:key="*this">
<view class="content-box">
<view style="display: flex; align-items: center; width: 90%">
<view style="color: #E6624A; font-size: 40px; font-weight: bold; margin-right: 30px">
{{index < 6 ? '0' + (index + 4) : index + 4}}
</view>
<view style="width: 100px; height: 100px; margin-right: 30px">
<image style="width: 100%; height: 100%; border-radius: 50%" src="{{item.contentAppendixUrl}}" mode="aspectFit"></image>
</view>
<view class="user_info" style="color: #333; font-size: 32px; margin-right: 30px">
{{item.content}}
<view> </view>
</view>
<view class="detail-content">
<view class="{{item.keywords == '精石之美' ? 'cont-icon1' : item.keywords == '突破之美' ? 'cont-icon2' : item.keywords == '进取之美' ? 'cont-icon3' : 'cont-icon4'}}">
{{item.keywords}}
</view>
</view>
</view>
<view class="score">
{{item.voteCount}}
<view style="font-size: 28px">票</view>
</view>
</view>
</block>
</view>
</view>
</view>
\ No newline at end of file
const {
get,
post
} = require('../../utils/request');
import url from '../../utils/urlconfig'
Page({
data: {
taskList: [],
type: ""
},
/**
* 生命周期函数--监听页面加载
*/
onLoad: function (options) {
if (options.type == 1) {
wx.setNavigationBarTitle({
title: '工作任务'
});
} else {
wx.setNavigationBarTitle({
title: '我要投票'
});
}
this.setData({
type: options.type
})
get(url.getWorkTaskListApi, {
pageNo: 1,
pageSize: 30,
}).then(res => {
this.setData({
taskList: res.data.records
})
})
},
handleTo(e) {
let item = e.currentTarget.dataset.item
if (item.finishState < 3) {
wx.navigateTo({
url: '/pages/allDescribe/index?id=' + item.id + '&bizType=' + item.bizType,
})
}
}
})
\ No newline at end of file
{
"usingComponents": {}
}
\ No newline at end of file
/* pages/workTask/index.wxss */
.task-out {
width: 96%;
margin: 0 auto;
.task-content{
display: flex;
margin: 10px 0;
.task-item-box{
padding: 8px 0;
margin-left: 15px;
display: flex;
flex-direction: column;
justify-content: space-between;
}
}
.task-img {
width: 180px;
height: 120px;
}
.task-name{
font-size: 18px;
}
.exam-over {
width: 80px;
padding: 6px 5px;
border: 1px solid #e5e6e8;
font-size: 16px;
background-color: #e5e6e8;
color: #999;
text-align: center;
border-radius: 30px;
}
.exam-finish {
width: 80px;
padding: 6px 5px;
border: 1px solid #cbeecd;
font-size: 16px;
color: #53af5c;
background-color: #cbeecd;
text-align: center;
border-radius: 30px;
}
.exam-start {
width: 80px;
padding: 6px 5px;
color: #e6624a;
border: 1px solid #e6624a;
font-size: 16px;
background-color: rgba(253, 63, 52, 0.05);
text-align: center;
border-radius: 30px;
}
}
\ No newline at end of file
<!--问卷调查,投票 中转页面-->
<view class="task-out">
<view wx:for="{{taskList}}" wx:key="id" >
<view data-item="{{item}}" wx:if="{{item.bizType == type}}" class="task-content" bind:tap="handleTo">
<view>
<image class="task-img" src="{{item.image}}" mode="aspectFill" />
</view>
<view class="task-item-box">
<text class="task-name">{{item.name}}</text>
<view data-item="{{item}}" class="{{(item.finishState == '0' || item.finishState == '3')? 'exam-over': (item.finishState == '1') ? 'exam-finish': 'exam-start'}} ">
{{item.finishState == " 0" ? "未开始" : item.finishState=="1" ? "已完成" : item.finishState=="2" ? "参与" : item.finishState=="3" ? "已过期" : item.finishState=="4" ? "未参与调查" : "" }}
</view>
</view>
</view>
</view>
</view>
\ No newline at end of file
{
"compileType": "miniprogram",
"libVersion": "trial",
"packOptions": {
"ignore": [],
"include": []
},
"setting": {
"coverView": true,
"es6": true,
"postcss": true,
"minified": true,
"enhance": true,
"showShadowRootInWxmlPanel": true,
"packNpmManually": true,
"packNpmRelationList": [
{
"packageJsonPath": "./package.json",
"miniprogramNpmDistDir": "./miniprogram_npm/"
}
],
"babelSetting": {
"ignore": [],
"disablePlugins": [],
"outputPath": ""
},
"useCompilerPlugins": [
"less"
]
},
"condition": {},
"editorSetting": {
"tabIndent": "auto",
"tabSize": 2
},
"appid": "wxa8cee13010567000"
}
\ No newline at end of file
{
"description": "项目私有配置文件。此文件中的内容将覆盖 project.config.json 中的相同字段。项目的改动优先同步到此文件中。详见文档:https://developers.weixin.qq.com/miniprogram/dev/devtools/projectconfig.html",
"projectname": "%E6%99%BA%E6%85%A7%E5%85%9A%E5%BB%BA%E5%B0%8F",
"setting": {
"compileHotReLoad": true
}
}
\ No newline at end of file
{
"desc": "关于本文件的更多信息,请参考文档 https://developers.weixin.qq.com/miniprogram/dev/framework/sitemap.html",
"rules": [{
"action": "allow",
"page": "*"
}]
}
\ No newline at end of file
// utils/request.js
const TOKEN_KEY = 'auth_token';
const tokenData = wx.getStorageSync(TOKEN_KEY);
function request(options) {
return new Promise((resolve, reject) => {
wx.request({
url: options.url+`?companyCode=zhdj&siteCode=edu`, // 拼接基础URL和接口路径
data: options.data || {}, // 请求参数
method: options.method,
header: {
'content-type': 'application/json', // 默认JSON格式
'Authorization': tokenData.token,
...options.header // 可以覆盖默认header
},
success: (res) => {
if (res.statusCode >= 200 && res.statusCode < 300) {
resolve(res.data); // 请求成功,解析数据并返回
} else {
if(res.data.code == '2002'){
wx.navigateTo({
url: '/pages/login/index',
})
}else{
reject(res); // 请求失败,返回错误信息1
}
}
},
fail: (error) => {
console.log(error,'22');
reject(error); // 请求失败,返回错误信息
}
});
});
}
module.exports = {
get: (url, data) => request({ url, data, method: 'GET' }),
post: (url, data) => request({ url, data, method: 'POST' }),
put: (url, data) => request({ url, data, method: 'PUT' }),
delete: (url, data) => request({ url, data, method: 'DELETE' })
};
\ No newline at end of file
const baseUrl = "https://hqjddj.shanghaiairport.com";
const url = {
baseUrl: baseUrl,
userInfoApi: `${baseUrl}/system/api/account/get`, //个人信息
saveUserInfoApi: `${baseUrl}/system/api/account/update`, //保存个人信息
meneItemApi: `${baseUrl}/web-student/api/system/my/item`,
homeItemApi: `${baseUrl}/web-student/api/portal/home/other/list`,
NewsMessageApi: `${baseUrl}/web-student/api/info/page/pcList`,
NewsResultListApi: `${baseUrl}/web-student/api/info/view`,
//图片,文件上传
uploadApi:`${baseUrl}/aliyun/api/upload`,
//搜索接口
searchApi: `${baseUrl}/web-student/api/portal/home/other/search`,
searchHistoryApi: `${baseUrl}/system/dictionary/home/searchListByMe`,
searchDeleteApi: `${baseUrl}/system/dictionary/home/searchDeleteByMe`,
searchListAllApi: `${baseUrl}/system/dictionary/home/searchListByAll`,
//修改密码
changPsdApi: `${baseUrl}/system/api/account/mobile/pwd/update`,
// 获取评论列表
getCommentListApi: `${baseUrl}/web-student/api/tpComment/comment/list`,
//点赞,取消点赞
trainReviewGoodApi: `${baseUrl}/web-student/api/tpCommentThumbsUp/save`,
trainReviewBadApi: `${baseUrl}/web-student/api/tpCommentThumbsUp/delete`,
// 回复评论
setcommentRaplyApi: `${baseUrl}/web-student/api/tpCommentReply/save`,
// 评论
setcommentApi: `${baseUrl}/web-student/api/tpComment/save`,
//收藏,取消收藏
setFavoriteApi: `${baseUrl}/web-student/api/studentCase/study/favorite`,
setCancelFavoriteApi: `${baseUrl}/web-student/api/studentCase/study/cancelFavorite`,
//获取工作任务列表
getWorkTaskListApi: `${baseUrl}/web-student/api/research/page/list`,
//获取任务详情介绍
getTaskDetailApi: `${baseUrl}/web-student/api/research/details`,
// 获取问卷
getQuestionnaireDataApi: `${baseUrl}/web-student/api/researchQuestion/last/next`,
//查看问卷结果
getAnswerApi: `${baseUrl}/web-student/api/researchAnswer/view`,
//获取我的item
getMineItemsApi: `${baseUrl}/web-student/api/system/my/item`,
//纪检信箱
systemMailboxApi: `${baseUrl}/web-manage/manage/systemMailbox/save/1`,
//党委书记信箱
dwsystemMailboxApi: `${baseUrl}/web-manage/manage/systemMailbox/save/2`,
//我要留言
setLeaveMesApi: `${baseUrl}/web-manage/manage/leaveWord/save`,
//我的诉求
myAppealListApi: `${baseUrl}/web-manage/manage/systemMailbox/selectMyPage`,
myMailboxApi: `${baseUrl}/web-manage/manage/systemMailbox/getById`,
myAppealDetailApi: `${baseUrl}/web-manage/manage/leaveWord/getById`,
//我的评论
myCommentListApi: `${baseUrl}/web-student/api/tpComment/pc/listByMyself`,
//投票列表数据
voteListApi: `${baseUrl}/web-student/api/researchQuestion/list/all`,
voteSumbitApi: `${baseUrl}/web-student/api/researchAnswer/submit`,
voteSumbitSecondApi: `${baseUrl}/web-student/api/researchQuestion/getVoteResult`,
voteTopApi: `${baseUrl}/web-student/api/researchQuestion/getVoteTop`,
//我要投稿
getContributeListApi: `${baseUrl}/system/dictionary/child/list`,
commitContributeApi: `${baseUrl}/web-manage/manage/site/classify/publication/insert`,
getSelectListApi: `${baseUrl}/system/manage/group/list/page`,
getContributeMyListApi: `${baseUrl}/web-manage/manage/site/classify/publication/list`, //我的投稿
//培训测试
getTrainingListApi: `${baseUrl}/web-student/api/info/page/pcList`, //培训列表
getExamListApi: `${baseUrl}/web-student/api/exam/list`, //测试列表
getExamDetatilApi: `${baseUrl}/web-student/api/exam/details`, //测试列表详情
getExamHistoryListApi: `${baseUrl}/web-student/api/exam/show/my/answer/result`, //测试历史
getQuestionItemApi: `${baseUrl}/web-student/api/exam/make`, //获取题
saveQuestionItemApi: `${baseUrl}/web-student/api/exam/save`, //提交每个题
// 活动服务
getActivityListApi: `${baseUrl}/web-student/api/trainingProject/page/list`, //获取活动列表
getactiveNavListApi: `${baseUrl}/web-student/api/trainingProject/getTrainingActivity`, //活动NavList
getActiveDetailApi: `${baseUrl}/web-student/api/trainingProject/one/detail/progress/view`, //活动详情
signUpApi: `${baseUrl}/web-student/api/enroll/student`, //活动报名
signInApi: `${baseUrl}/web-student/api/sign/scan`, //活动线上签到
signCustomInApi: `${baseUrl}/web-student/api/sign/custom/scan`, //活动扫码签到
myCaseFavorites: `${baseUrl}/web-student/api/studentCase/study/getFavorites`, //我的作品收藏
myHistory: `${baseUrl}/web-student/api/portal/home/other/history`, //我的作品收藏
getPointDetailApi: `${baseUrl}/web-student/pc/point/getPointDetail`, //积分商城
};
export default url;
\ No newline at end of file
const formatTime = date => {
const year = date.getFullYear()
const month = date.getMonth() + 1
const day = date.getDate()
const hour = date.getHours()
const minute = date.getMinutes()
const second = date.getSeconds()
return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
}
const formatNumber = n => {
n = n.toString()
return n[1] ? n : `0${n}`
}
const formatRichText = function (html) {
let newContent = html.replace(/<img[^>]*>/gi, function (match, capture) {
match = match.replace(/style="[^"]+"/gi, '').replace(/style='[^']+'/gi, '');
match = match.replace(/width="[^"]+"/gi, '').replace(/width='[^']+'/gi, '');
match = match.replace(/height="[^"]+"/gi, '').replace(/height='[^']+'/gi, '');
match = match.replace(/&amp;/gi, '&')
return match;
});
newContent = newContent.replace(/style="[^"]+"/gi, function (match, capture) {
match = match
.replace(/<p>/gi, '<p class="p_class">')
.replace(/width:[^;]+;/gi, 'max-width:100%;')
.replace(/width:[^;]+;/gi, 'max-width:100%;');
return match;
});
newContent = newContent.replace(/<br[^>]*\/>/gi, "");
newContent = newContent.replace(/&nbsp;/gi, '<br />');
newContent = newContent.replace(/<a>/gi, "<a class='a_class'");
newContent = newContent.replace(/<li/gi, "<li class='li_class'");
newContent = newContent.replace(/\<p/gi, "<p class='p_class'");
newContent = newContent.replace(/<\/p>/g, '</p>');
newContent = newContent.replace(/\<span/gi, "<span class='span_class'");
newContent = newContent.replace(/<strong>/gi, '<strong class="strong_class">');
// newContent = newContent.replace(/\<img/gi, '<image style="width:100%;height:300px;margin-top:10rpx;margin-bottom:10rpx;" mode="widthFix"');
newContent = newContent.replace(/<img.*?src="(.*?)".*?>/g, '<img src="$1" class="image_class" mode="aspectFill"></image>')
return newContent;
}
module.exports = {
formatTime,
formatRichText
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment