diff --git a/cloudfunctions/imProcess/index.js b/cloudfunctions/imProcess/index.js index bd713fa7..e4f0a25e 100644 --- a/cloudfunctions/imProcess/index.js +++ b/cloudfunctions/imProcess/index.js @@ -9,8 +9,6 @@ const _ = db.command; const sharp = require('sharp'); const { registerFont } = require('canvas'); const text2png = require('text2png'); -// const sizeOf = require("buffer-image-size"); -// const { async } = require('../../miniprogram/packages/regenerator-runtime/runtime'); var assert = require('assert'); registerFont('./方正黑体-GBK.TTF', {family: 'FZHei'}); diff --git a/cloudfunctions/relationOp/config.json b/cloudfunctions/relationOp/config.json new file mode 100644 index 00000000..5ecc33e5 --- /dev/null +++ b/cloudfunctions/relationOp/config.json @@ -0,0 +1,6 @@ +{ + "permissions": { + "openapi": [ + ] + } +} \ No newline at end of file diff --git a/cloudfunctions/relationOp/index.js b/cloudfunctions/relationOp/index.js new file mode 100644 index 00000000..82b543b9 --- /dev/null +++ b/cloudfunctions/relationOp/index.js @@ -0,0 +1,54 @@ +// 云函数入口文件 +const cloud = require('wx-server-sdk'); + +cloud.init({ + env: cloud.DYNAMIC_CURRENT_ENV +}); +const db = cloud.database(); +const _ = db.command; + +// 权限检查 +async function check_manager(level) { + const wxContext = cloud.getWXContext() + const openid = wxContext.OPENID; + const isManager = (await cloud.callFunction({ + name: 'isManager', + data: { + openid: openid, + req: level + } + })); + return isManager; +} + +// 云函数入口函数 +exports.main = async (event, context) => { + if (event.deploy_test === true) { + // 进行部署检查 + return; + } + const type = event.type; + + if (type == "saveRelationTypes") { + // 新建关系类型 + if (!event.relationTypes) { + return false; + } + return await db.collection("setting").doc("relation").update({ + data: { + types: event.relationTypes + } + }); + } + if (type == "saveRelation") { + var cat_id = event.cat_id; + var relations = event.relations; + return await db.collection("cat").doc(cat_id).update({ + data: { + relations: relations + } + }); + } + + return `unk type ${type}`; +} \ No newline at end of file diff --git a/cloudfunctions/relationOp/package.json b/cloudfunctions/relationOp/package.json new file mode 100644 index 00000000..69248a63 --- /dev/null +++ b/cloudfunctions/relationOp/package.json @@ -0,0 +1,14 @@ +{ + "name": "relationOp", + "version": "1.0.0", + "description": "", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1" + }, + "author": "", + "license": "ISC", + "dependencies": { + "wx-server-sdk": "~2.6.3" + } +} \ No newline at end of file diff --git a/miniprogram/app.js b/miniprogram/app.js index fcb2a193..08491943 100644 --- a/miniprogram/app.js +++ b/miniprogram/app.js @@ -20,7 +20,7 @@ App({ checkUpdateVersion(); this.globalData = { - version: "v1.8.1" + version: "v1.8.3" } } }) diff --git a/miniprogram/app.json b/miniprogram/app.json index 34438fd2..9618e904 100644 --- a/miniprogram/app.json +++ b/miniprogram/app.json @@ -1,71 +1,73 @@ { - "pages": [ - "pages/genealogy/genealogy", - "pages/genealogy/addPhoto/addPhoto", - "pages/genealogy/detailCat/detailCat", - "pages/info/info", - "pages/info/photoRank/photoRank", - "pages/info/reward/reward", - "pages/info/feedback/feedback", - "pages/info/feedback/myFeedback/myFeedback", - "pages/info/devTeam/devTeam", - "pages/manage/addCat/addCat", - "pages/manage/imProcess/imProcess", - "pages/manage/checkPhotos/checkPhotos", - "pages/manage/filters/filters", - "pages/debug/debug", - "pages/manage/managers/managers", - "pages/genealogy/feedbackDetail/feedbackDetail", - "pages/manage/checkFeedbacks/checkFeedbacks", - "pages/manage/replyFeedback/replyFeedback", - "pages/manage/rewards/rewards", - "pages/recognize/recognize", - "pages/genealogy/commentBoard/commentBoard", - "pages/debug/deployTip/deployTip", - "pages/news/news", - "pages/news/detailNews/detailNews", - "pages/news/modifyNews/modifyNews", - "pages/news/createNews/createNews", - "pages/news/sciDetail/sciDetail" - ], - "tabBar": { - "selectedColor": "#000", - "borderStyle": "white", - "list": [ - { - "pagePath": "pages/genealogy/genealogy", - "iconPath": "./images/tabs/default/cat.png", - "selectedIconPath": "./images/tabs/active/cat.png", - "text": "猫谱" - }, - { - "pagePath": "pages/news/news", - "iconPath": "./images/tabs/default/sci.png", - "selectedIconPath": "./images/tabs/active/sci.png", - "text": "公告" - }, - { - "pagePath": "pages/info/info", - "iconPath": "./images/tabs/default/info.png", - "selectedIconPath": "./images/tabs/active/info.png", - "text": "关于" - } - ] - }, - "window": { - "backgroundColor": "#fff", - "backgroundTextStyle": "light", - "navigationBarBackgroundColor": "#ffd101", - "navigationBarTitleText": "中大猫谱", - "navigationBarTextStyle": "black" - }, - "supportedMaterials": [ - { - "materialType": "image/*", - "name": "用${nickname}识别", - "desc": "根据图片识别校园中相似的猫咪", - "path": "pages/recognize/recognize" - } - ], - "sitemapLocation": "sitemap.json" + "pages": [ + "pages/genealogy/genealogy", + "pages/genealogy/addPhoto/addPhoto", + "pages/genealogy/detailCat/detailCat", + "pages/info/info", + "pages/info/photoRank/photoRank", + "pages/info/reward/reward", + "pages/info/feedback/feedback", + "pages/info/feedback/myFeedback/myFeedback", + "pages/info/devTeam/devTeam", + "pages/manage/addCat/addCat", + "pages/manage/imProcess/imProcess", + "pages/manage/checkPhotos/checkPhotos", + "pages/manage/filters/filters", + "pages/debug/debug", + "pages/manage/managers/managers", + "pages/genealogy/feedbackDetail/feedbackDetail", + "pages/manage/checkFeedbacks/checkFeedbacks", + "pages/manage/replyFeedback/replyFeedback", + "pages/manage/rewards/rewards", + "pages/recognize/recognize", + "pages/genealogy/commentBoard/commentBoard", + "pages/debug/deployTip/deployTip", + "pages/news/news", + "pages/news/detailNews/detailNews", + "pages/news/modifyNews/modifyNews", + "pages/news/createNews/createNews", + "pages/news/sciDetail/sciDetail", + "pages/manage/addRelations/addRelations" + ], + "tabBar": { + "selectedColor": "#000", + "borderStyle": "white", + "list": [ + { + "pagePath": "pages/genealogy/genealogy", + "iconPath": "./images/tabs/default/cat.png", + "selectedIconPath": "./images/tabs/active/cat.png", + "text": "猫谱" + }, + { + "pagePath": "pages/news/news", + "iconPath": "./images/tabs/default/sci.png", + "selectedIconPath": "./images/tabs/active/sci.png", + "text": "公告" + }, + { + "pagePath": "pages/info/info", + "iconPath": "./images/tabs/default/info.png", + "selectedIconPath": "./images/tabs/active/info.png", + "text": "关于" + } + ] + }, + "window": { + "backgroundColor": "#fff", + "backgroundTextStyle": "light", + "navigationBarBackgroundColor": "#ffd101", + "navigationBarTitleText": "中大猫谱", + "navigationBarTextStyle": "black" + }, + "supportedMaterials": [ + { + "materialType": "image/*", + "name": "用${nickname}识别", + "desc": "根据图片识别校园中相似的猫咪", + "path": "pages/recognize/recognize" + } + ], + "sitemapLocation": "sitemap.json", + "lazyCodeLoading" : "requiredComponents" } \ No newline at end of file diff --git a/miniprogram/cache.js b/miniprogram/cache.js index 6d57f7bd..36c9e3de 100644 --- a/miniprogram/cache.js +++ b/miniprogram/cache.js @@ -7,7 +7,8 @@ function getCacheItem(key) { } // 过期了 - if (new Date() < new Date(data.expire_date)) { + if (new Date() > new Date(data.expire_date)) { + console.log(`${key} expired.`); return undefined; } diff --git a/miniprogram/cat.js b/miniprogram/cat.js index 616d9551..789ea7eb 100644 --- a/miniprogram/cat.js +++ b/miniprogram/cat.js @@ -5,13 +5,20 @@ const cache = require('./cache.js'); // 常用的一些对象 const db = wx.cloud.database(); const coll_photo = db.collection('photo'); +const coll_cat = db.collection('cat'); // 获取猫猫的封面图 -// TODO(zing): 可以搞个缓存 async function getAvatar(cat_id, total) { if (!total || total === 0) { return undefined; } + + var cacheKey = `cat-avatar-${cat_id}`; + var cacheItem = cache.getCacheItem(cacheKey); + console.log(cacheKey, cacheItem); + if (cacheItem) { + return cacheItem; + } // photo_id : 不以 HEIC 为文件后缀的字符串 const qf = { @@ -24,7 +31,10 @@ async function getAvatar(cat_id, total) { // TODO: 这里对于API调用的次数较多,需要修改 var index = utils.randomInt(0, total); var pho_src = (await coll_photo.where(qf).skip(index).limit(1).get()).data; - return pho_src[0]; + cacheItem = pho_src[0]; + + cache.setCacheItem(cacheKey, cacheItem, 24); + return cacheItem; } // 消除“有新相片”提示 @@ -38,8 +48,25 @@ function setVisitedDate(cat_id) { return; } +// 获取猫猫信息 +async function getCatItem(cat_id) { + if (!cat_id) { + return undefined; + } + var cacheKey = `cat-item-${cat_id}`; + var cacheItem = cache.getCacheItem(cacheKey); + if (cacheItem) { + return cacheItem; + } + + cacheItem = (await coll_cat.doc(cat_id).get()).data; + cache.setCacheItem(cacheKey, cacheItem, 24); + return cacheItem; +} + export { getAvatar, getVisitedDate, setVisitedDate, + getCatItem, } \ No newline at end of file diff --git a/miniprogram/images/recognize/share_cover.jpg b/miniprogram/images/recognize/share_cover.jpg index 8c9e3caa..ba30d98e 100644 Binary files a/miniprogram/images/recognize/share_cover.jpg and b/miniprogram/images/recognize/share_cover.jpg differ diff --git a/miniprogram/packages/regenerator-runtime/README.md b/miniprogram/packages/regenerator-runtime/README.md deleted file mode 100644 index d93386a3..00000000 --- a/miniprogram/packages/regenerator-runtime/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# regenerator-runtime - -Standalone runtime for -[Regenerator](https://github.com/facebook/regenerator)-compiled generator -and `async` functions. - -To import the runtime as a module (recommended), either of the following -import styles will work: -```js -// CommonJS -const regeneratorRuntime = require("regenerator-runtime"); - -// ECMAScript 2015 -import regeneratorRuntime from "regenerator-runtime"; -``` - -To ensure that `regeneratorRuntime` is defined globally, either of the -following styles will work: -```js -// CommonJS -require("regenerator-runtime/runtime"); - -// ECMAScript 2015 -import "regenerator-runtime/runtime"; -``` - -To get the absolute file system path of `runtime.js`, evaluate the -following expression: -```js -require("regenerator-runtime/path").path -``` diff --git a/miniprogram/packages/regenerator-runtime/package.json b/miniprogram/packages/regenerator-runtime/package.json deleted file mode 100644 index 20caa040..00000000 --- a/miniprogram/packages/regenerator-runtime/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "regenerator-runtime", - "author": "Ben Newman ", - "description": "Runtime for Regenerator-compiled generator and async functions.", - "version": "0.13.1", - "main": "runtime.js", - "keywords": [ - "regenerator", - "runtime", - "generator", - "async" - ], - "repository": { - "type": "git", - "url": "https://github.com/facebook/regenerator/tree/master/packages/regenerator-runtime" - }, - "license": "MIT" -} diff --git a/miniprogram/packages/regenerator-runtime/path.js b/miniprogram/packages/regenerator-runtime/path.js deleted file mode 100644 index ced878b8..00000000 --- a/miniprogram/packages/regenerator-runtime/path.js +++ /dev/null @@ -1,11 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -exports.path = require("path").join( - __dirname, - "runtime.js" -); diff --git a/miniprogram/packages/regenerator-runtime/runtime.js b/miniprogram/packages/regenerator-runtime/runtime.js deleted file mode 100644 index 51336875..00000000 --- a/miniprogram/packages/regenerator-runtime/runtime.js +++ /dev/null @@ -1,714 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -var regeneratorRuntime = (function (exports) { - "use strict"; - - var Op = Object.prototype; - var hasOwn = Op.hasOwnProperty; - var undefined; // More compressible than void 0. - var $Symbol = typeof Symbol === "function" ? Symbol : {}; - var iteratorSymbol = $Symbol.iterator || "@@iterator"; - var asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator"; - var toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag"; - - function wrap(innerFn, outerFn, self, tryLocsList) { - // If outerFn provided and outerFn.prototype is a Generator, then outerFn.prototype instanceof Generator. - var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator; - var generator = Object.create(protoGenerator.prototype); - var context = new Context(tryLocsList || []); - - // The ._invoke method unifies the implementations of the .next, - // .throw, and .return methods. - generator._invoke = makeInvokeMethod(innerFn, self, context); - - return generator; - } - exports.wrap = wrap; - - // Try/catch helper to minimize deoptimizations. Returns a completion - // record like context.tryEntries[i].completion. This interface could - // have been (and was previously) designed to take a closure to be - // invoked without arguments, but in all the cases we care about we - // already have an existing method we want to call, so there's no need - // to create a new function object. We can even get away with assuming - // the method takes exactly one argument, since that happens to be true - // in every case, so we don't have to touch the arguments object. The - // only additional allocation required is the completion record, which - // has a stable shape and so hopefully should be cheap to allocate. - function tryCatch(fn, obj, arg) { - try { - return { type: "normal", arg: fn.call(obj, arg) }; - } catch (err) { - return { type: "throw", arg: err }; - } - } - - var GenStateSuspendedStart = "suspendedStart"; - var GenStateSuspendedYield = "suspendedYield"; - var GenStateExecuting = "executing"; - var GenStateCompleted = "completed"; - - // Returning this object from the innerFn has the same effect as - // breaking out of the dispatch switch statement. - var ContinueSentinel = {}; - - // Dummy constructor functions that we use as the .constructor and - // .constructor.prototype properties for functions that return Generator - // objects. For full spec compliance, you may wish to configure your - // minifier not to mangle the names of these two functions. - function Generator() {} - function GeneratorFunction() {} - function GeneratorFunctionPrototype() {} - - // This is a polyfill for %IteratorPrototype% for environments that - // don't natively support it. - var IteratorPrototype = {}; - IteratorPrototype[iteratorSymbol] = function () { - return this; - }; - - var getProto = Object.getPrototypeOf; - var NativeIteratorPrototype = getProto && getProto(getProto(values([]))); - if (NativeIteratorPrototype && - NativeIteratorPrototype !== Op && - hasOwn.call(NativeIteratorPrototype, iteratorSymbol)) { - // This environment has a native %IteratorPrototype%; use it instead - // of the polyfill. - IteratorPrototype = NativeIteratorPrototype; - } - - var Gp = GeneratorFunctionPrototype.prototype = - Generator.prototype = Object.create(IteratorPrototype); - GeneratorFunction.prototype = Gp.constructor = GeneratorFunctionPrototype; - GeneratorFunctionPrototype.constructor = GeneratorFunction; - GeneratorFunctionPrototype[toStringTagSymbol] = - GeneratorFunction.displayName = "GeneratorFunction"; - - // Helper for defining the .next, .throw, and .return methods of the - // Iterator interface in terms of a single ._invoke method. - function defineIteratorMethods(prototype) { - ["next", "throw", "return"].forEach(function(method) { - prototype[method] = function(arg) { - return this._invoke(method, arg); - }; - }); - } - - exports.isGeneratorFunction = function(genFun) { - var ctor = typeof genFun === "function" && genFun.constructor; - return ctor - ? ctor === GeneratorFunction || - // For the native GeneratorFunction constructor, the best we can - // do is to check its .name property. - (ctor.displayName || ctor.name) === "GeneratorFunction" - : false; - }; - - exports.mark = function(genFun) { - if (Object.setPrototypeOf) { - Object.setPrototypeOf(genFun, GeneratorFunctionPrototype); - } else { - genFun.__proto__ = GeneratorFunctionPrototype; - if (!(toStringTagSymbol in genFun)) { - genFun[toStringTagSymbol] = "GeneratorFunction"; - } - } - genFun.prototype = Object.create(Gp); - return genFun; - }; - - // Within the body of any async function, `await x` is transformed to - // `yield regeneratorRuntime.awrap(x)`, so that the runtime can test - // `hasOwn.call(value, "__await")` to determine if the yielded value is - // meant to be awaited. - exports.awrap = function(arg) { - return { __await: arg }; - }; - - function AsyncIterator(generator) { - function invoke(method, arg, resolve, reject) { - var record = tryCatch(generator[method], generator, arg); - if (record.type === "throw") { - reject(record.arg); - } else { - var result = record.arg; - var value = result.value; - if (value && - typeof value === "object" && - hasOwn.call(value, "__await")) { - return Promise.resolve(value.__await).then(function(value) { - invoke("next", value, resolve, reject); - }, function(err) { - invoke("throw", err, resolve, reject); - }); - } - - return Promise.resolve(value).then(function(unwrapped) { - // When a yielded Promise is resolved, its final value becomes - // the .value of the Promise<{value,done}> result for the - // current iteration. - result.value = unwrapped; - resolve(result); - }, function(error) { - // If a rejected Promise was yielded, throw the rejection back - // into the async generator function so it can be handled there. - return invoke("throw", error, resolve, reject); - }); - } - } - - var previousPromise; - - function enqueue(method, arg) { - function callInvokeWithMethodAndArg() { - return new Promise(function(resolve, reject) { - invoke(method, arg, resolve, reject); - }); - } - - return previousPromise = - // If enqueue has been called before, then we want to wait until - // all previous Promises have been resolved before calling invoke, - // so that results are always delivered in the correct order. If - // enqueue has not been called before, then it is important to - // call invoke immediately, without waiting on a callback to fire, - // so that the async generator function has the opportunity to do - // any necessary setup in a predictable way. This predictability - // is why the Promise constructor synchronously invokes its - // executor callback, and why async functions synchronously - // execute code before the first await. Since we implement simple - // async functions in terms of async generators, it is especially - // important to get this right, even though it requires care. - previousPromise ? previousPromise.then( - callInvokeWithMethodAndArg, - // Avoid propagating failures to Promises returned by later - // invocations of the iterator. - callInvokeWithMethodAndArg - ) : callInvokeWithMethodAndArg(); - } - - // Define the unified helper method that is used to implement .next, - // .throw, and .return (see defineIteratorMethods). - this._invoke = enqueue; - } - - defineIteratorMethods(AsyncIterator.prototype); - AsyncIterator.prototype[asyncIteratorSymbol] = function () { - return this; - }; - exports.AsyncIterator = AsyncIterator; - - // Note that simple async functions are implemented on top of - // AsyncIterator objects; they just return a Promise for the value of - // the final result produced by the iterator. - exports.async = function(innerFn, outerFn, self, tryLocsList) { - var iter = new AsyncIterator( - wrap(innerFn, outerFn, self, tryLocsList) - ); - - return exports.isGeneratorFunction(outerFn) - ? iter // If outerFn is a generator, return the full iterator. - : iter.next().then(function(result) { - return result.done ? result.value : iter.next(); - }); - }; - - function makeInvokeMethod(innerFn, self, context) { - var state = GenStateSuspendedStart; - - return function invoke(method, arg) { - if (state === GenStateExecuting) { - throw new Error("Generator is already running"); - } - - if (state === GenStateCompleted) { - if (method === "throw") { - throw arg; - } - - // Be forgiving, per 25.3.3.3.3 of the spec: - // https://people.mozilla.org/~jorendorff/es6-draft.html#sec-generatorresume - return doneResult(); - } - - context.method = method; - context.arg = arg; - - while (true) { - var delegate = context.delegate; - if (delegate) { - var delegateResult = maybeInvokeDelegate(delegate, context); - if (delegateResult) { - if (delegateResult === ContinueSentinel) continue; - return delegateResult; - } - } - - if (context.method === "next") { - // Setting context._sent for legacy support of Babel's - // function.sent implementation. - context.sent = context._sent = context.arg; - - } else if (context.method === "throw") { - if (state === GenStateSuspendedStart) { - state = GenStateCompleted; - throw context.arg; - } - - context.dispatchException(context.arg); - - } else if (context.method === "return") { - context.abrupt("return", context.arg); - } - - state = GenStateExecuting; - - var record = tryCatch(innerFn, self, context); - if (record.type === "normal") { - // If an exception is thrown from innerFn, we leave state === - // GenStateExecuting and loop back for another invocation. - state = context.done - ? GenStateCompleted - : GenStateSuspendedYield; - - if (record.arg === ContinueSentinel) { - continue; - } - - return { - value: record.arg, - done: context.done - }; - - } else if (record.type === "throw") { - state = GenStateCompleted; - // Dispatch the exception by looping back around to the - // context.dispatchException(context.arg) call above. - context.method = "throw"; - context.arg = record.arg; - } - } - }; - } - - // Call delegate.iterator[context.method](context.arg) and handle the - // result, either by returning a { value, done } result from the - // delegate iterator, or by modifying context.method and context.arg, - // setting context.delegate to null, and returning the ContinueSentinel. - function maybeInvokeDelegate(delegate, context) { - var method = delegate.iterator[context.method]; - if (method === undefined) { - // A .throw or .return when the delegate iterator has no .throw - // method always terminates the yield* loop. - context.delegate = null; - - if (context.method === "throw") { - // Note: ["return"] must be used for ES3 parsing compatibility. - if (delegate.iterator["return"]) { - // If the delegate iterator has a return method, give it a - // chance to clean up. - context.method = "return"; - context.arg = undefined; - maybeInvokeDelegate(delegate, context); - - if (context.method === "throw") { - // If maybeInvokeDelegate(context) changed context.method from - // "return" to "throw", let that override the TypeError below. - return ContinueSentinel; - } - } - - context.method = "throw"; - context.arg = new TypeError( - "The iterator does not provide a 'throw' method"); - } - - return ContinueSentinel; - } - - var record = tryCatch(method, delegate.iterator, context.arg); - - if (record.type === "throw") { - context.method = "throw"; - context.arg = record.arg; - context.delegate = null; - return ContinueSentinel; - } - - var info = record.arg; - - if (! info) { - context.method = "throw"; - context.arg = new TypeError("iterator result is not an object"); - context.delegate = null; - return ContinueSentinel; - } - - if (info.done) { - // Assign the result of the finished delegate to the temporary - // variable specified by delegate.resultName (see delegateYield). - context[delegate.resultName] = info.value; - - // Resume execution at the desired location (see delegateYield). - context.next = delegate.nextLoc; - - // If context.method was "throw" but the delegate handled the - // exception, let the outer generator proceed normally. If - // context.method was "next", forget context.arg since it has been - // "consumed" by the delegate iterator. If context.method was - // "return", allow the original .return call to continue in the - // outer generator. - if (context.method !== "return") { - context.method = "next"; - context.arg = undefined; - } - - } else { - // Re-yield the result returned by the delegate method. - return info; - } - - // The delegate iterator is finished, so forget it and continue with - // the outer generator. - context.delegate = null; - return ContinueSentinel; - } - - // Define Generator.prototype.{next,throw,return} in terms of the - // unified ._invoke helper method. - defineIteratorMethods(Gp); - - Gp[toStringTagSymbol] = "Generator"; - - // A Generator should always return itself as the iterator object when the - // @@iterator function is called on it. Some browsers' implementations of the - // iterator prototype chain incorrectly implement this, causing the Generator - // object to not be returned from this call. This ensures that doesn't happen. - // See https://github.com/facebook/regenerator/issues/274 for more details. - Gp[iteratorSymbol] = function() { - return this; - }; - - Gp.toString = function() { - return "[object Generator]"; - }; - - function pushTryEntry(locs) { - var entry = { tryLoc: locs[0] }; - - if (1 in locs) { - entry.catchLoc = locs[1]; - } - - if (2 in locs) { - entry.finallyLoc = locs[2]; - entry.afterLoc = locs[3]; - } - - this.tryEntries.push(entry); - } - - function resetTryEntry(entry) { - var record = entry.completion || {}; - record.type = "normal"; - delete record.arg; - entry.completion = record; - } - - function Context(tryLocsList) { - // The root entry object (effectively a try statement without a catch - // or a finally block) gives us a place to store values thrown from - // locations where there is no enclosing try statement. - this.tryEntries = [{ tryLoc: "root" }]; - tryLocsList.forEach(pushTryEntry, this); - this.reset(true); - } - - exports.keys = function(object) { - var keys = []; - for (var key in object) { - keys.push(key); - } - keys.reverse(); - - // Rather than returning an object with a next method, we keep - // things simple and return the next function itself. - return function next() { - while (keys.length) { - var key = keys.pop(); - if (key in object) { - next.value = key; - next.done = false; - return next; - } - } - - // To avoid creating an additional object, we just hang the .value - // and .done properties off the next function object itself. This - // also ensures that the minifier will not anonymize the function. - next.done = true; - return next; - }; - }; - - function values(iterable) { - if (iterable) { - var iteratorMethod = iterable[iteratorSymbol]; - if (iteratorMethod) { - return iteratorMethod.call(iterable); - } - - if (typeof iterable.next === "function") { - return iterable; - } - - if (!isNaN(iterable.length)) { - var i = -1, next = function next() { - while (++i < iterable.length) { - if (hasOwn.call(iterable, i)) { - next.value = iterable[i]; - next.done = false; - return next; - } - } - - next.value = undefined; - next.done = true; - - return next; - }; - - return next.next = next; - } - } - - // Return an iterator with no values. - return { next: doneResult }; - } - exports.values = values; - - function doneResult() { - return { value: undefined, done: true }; - } - - Context.prototype = { - constructor: Context, - - reset: function(skipTempReset) { - this.prev = 0; - this.next = 0; - // Resetting context._sent for legacy support of Babel's - // function.sent implementation. - this.sent = this._sent = undefined; - this.done = false; - this.delegate = null; - - this.method = "next"; - this.arg = undefined; - - this.tryEntries.forEach(resetTryEntry); - - if (!skipTempReset) { - for (var name in this) { - // Not sure about the optimal order of these conditions: - if (name.charAt(0) === "t" && - hasOwn.call(this, name) && - !isNaN(+name.slice(1))) { - this[name] = undefined; - } - } - } - }, - - stop: function() { - this.done = true; - - var rootEntry = this.tryEntries[0]; - var rootRecord = rootEntry.completion; - if (rootRecord.type === "throw") { - throw rootRecord.arg; - } - - return this.rval; - }, - - dispatchException: function(exception) { - if (this.done) { - throw exception; - } - - var context = this; - function handle(loc, caught) { - record.type = "throw"; - record.arg = exception; - context.next = loc; - - if (caught) { - // If the dispatched exception was caught by a catch block, - // then let that catch block handle the exception normally. - context.method = "next"; - context.arg = undefined; - } - - return !! caught; - } - - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - var record = entry.completion; - - if (entry.tryLoc === "root") { - // Exception thrown outside of any try block that could handle - // it, so set the completion value of the entire function to - // throw the exception. - return handle("end"); - } - - if (entry.tryLoc <= this.prev) { - var hasCatch = hasOwn.call(entry, "catchLoc"); - var hasFinally = hasOwn.call(entry, "finallyLoc"); - - if (hasCatch && hasFinally) { - if (this.prev < entry.catchLoc) { - return handle(entry.catchLoc, true); - } else if (this.prev < entry.finallyLoc) { - return handle(entry.finallyLoc); - } - - } else if (hasCatch) { - if (this.prev < entry.catchLoc) { - return handle(entry.catchLoc, true); - } - - } else if (hasFinally) { - if (this.prev < entry.finallyLoc) { - return handle(entry.finallyLoc); - } - - } else { - throw new Error("try statement without catch or finally"); - } - } - } - }, - - abrupt: function(type, arg) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.tryLoc <= this.prev && - hasOwn.call(entry, "finallyLoc") && - this.prev < entry.finallyLoc) { - var finallyEntry = entry; - break; - } - } - - if (finallyEntry && - (type === "break" || - type === "continue") && - finallyEntry.tryLoc <= arg && - arg <= finallyEntry.finallyLoc) { - // Ignore the finally entry if control is not jumping to a - // location outside the try/catch block. - finallyEntry = null; - } - - var record = finallyEntry ? finallyEntry.completion : {}; - record.type = type; - record.arg = arg; - - if (finallyEntry) { - this.method = "next"; - this.next = finallyEntry.finallyLoc; - return ContinueSentinel; - } - - return this.complete(record); - }, - - complete: function(record, afterLoc) { - if (record.type === "throw") { - throw record.arg; - } - - if (record.type === "break" || - record.type === "continue") { - this.next = record.arg; - } else if (record.type === "return") { - this.rval = this.arg = record.arg; - this.method = "return"; - this.next = "end"; - } else if (record.type === "normal" && afterLoc) { - this.next = afterLoc; - } - - return ContinueSentinel; - }, - - finish: function(finallyLoc) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.finallyLoc === finallyLoc) { - this.complete(entry.completion, entry.afterLoc); - resetTryEntry(entry); - return ContinueSentinel; - } - } - }, - - "catch": function(tryLoc) { - for (var i = this.tryEntries.length - 1; i >= 0; --i) { - var entry = this.tryEntries[i]; - if (entry.tryLoc === tryLoc) { - var record = entry.completion; - if (record.type === "throw") { - var thrown = record.arg; - resetTryEntry(entry); - } - return thrown; - } - } - - // The context.catch method must only be called with a location - // argument that corresponds to a known catch block. - throw new Error("illegal catch attempt"); - }, - - delegateYield: function(iterable, resultName, nextLoc) { - this.delegate = { - iterator: values(iterable), - resultName: resultName, - nextLoc: nextLoc - }; - - if (this.method === "next") { - // Deliberately forget the last sent value so that we don't - // accidentally pass it on to the delegate. - this.arg = undefined; - } - - return ContinueSentinel; - } - }; - - // Regardless of whether this script is executing as a CommonJS module - // or not, return the runtime object so that we can declare the variable - // regeneratorRuntime in the outer scope, which allows this module to be - // injected easily by `bin/regenerator --include-runtime script.js`. - return exports; - -}( - // If this script is executing as a CommonJS module, use module.exports - // as the regeneratorRuntime namespace. Otherwise create a new empty - // object. Either way, the resulting object will be used to initialize - // the regeneratorRuntime variable at the top of this file. - typeof module === "object" ? module.exports : {} -)); - - -module.exports = { regeneratorRuntime }; \ No newline at end of file diff --git a/miniprogram/packages/weui/package.json b/miniprogram/packages/weui/package.json deleted file mode 100644 index 77faaaff..00000000 --- a/miniprogram/packages/weui/package.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "name": "weui-miniprogram", - "version": "0.2.0", - "description": "", - "author": "xushengni,tomylin,cunjinli,rockhou", - "license": "MIT" -} \ No newline at end of file diff --git a/miniprogram/pages/debug/deployTip/deployConfig.js b/miniprogram/pages/debug/deployTip/deployConfig.js index 65fdf0e8..6f16b1ab 100644 --- a/miniprogram/pages/debug/deployTip/deployConfig.js +++ b/miniprogram/pages/debug/deployTip/deployConfig.js @@ -118,6 +118,10 @@ const init_setting = [{ "receiverNum": 2 } }, + { + "_id": "relation", + "types": ["好友", "情侣", "兄弟", "姐妹", "爸爸", "妈妈", "儿子", "女儿"] + } ] // 部署流程(不要修改!) @@ -127,7 +131,7 @@ module.exports = { "addPop", "commentCheck", "commentOp", "countPhoto", "getAllSci", "getMpCode", "getPhotoRank", "imProcess", "initDeploy", "interOp", "isManager", "manageFeedback", "managePhoto", "sendMsgV2", "updateCat", "updateFilter", "updateManager", - "updateReward", "userOp", "newsOp" + "updateReward", "userOp", "newsOp", "relationOp" ], default_init_data_id: default_init_data_id, collections: { diff --git a/miniprogram/pages/genealogy/detailCat/detailCat.js b/miniprogram/pages/genealogy/detailCat/detailCat.js index 97c1b6e9..08ecc764 100644 --- a/miniprogram/pages/genealogy/detailCat/detailCat.js +++ b/miniprogram/pages/genealogy/detailCat/detailCat.js @@ -6,11 +6,14 @@ const getGlobalSettings = utils.getGlobalSettings; const checkCanUpload = utils.checkCanUpload; const checkMultiClick = utils.checkMultiClick; const formatDate = utils.formatDate; +const isManager = utils.isManager; const getCatCommentCount = require('../../../comment.js').getCatCommentCount; const cat_utils = require('../../../cat.js'); const setVisitedDate = cat_utils.setVisitedDate; +const getAvatar = cat_utils.getAvatar; +const getCatItem = cat_utils.getCatItem; const text_cfg = config.text; @@ -31,6 +34,8 @@ var infoHeight = 0; // 单位是px var heights = {}; // 系统的各种heights +var context = {}; // 切换页面时记录一下context + // 获取照片的排序功能 const photoOrder = [ {key: 'shooting_date', order: 'desc', name: '最近拍摄'}, @@ -70,26 +75,19 @@ Page({ * 生命周期函数--监听页面加载 */ onLoad: function (options) { + if (cat_id != undefined) { + // 说明是从其他猫猫跳转过来的,记录下上下文 + context.cat_id = cat_id; + context.album_raw = album_raw; + } cat_id = options.cat_id; - // 开始加载页面 - const that = this; - getGlobalSettings('detailCat').then(settings => { - // 先把设置拿到 - page_settings = settings; - that.setData({ - photoPopWeight: settings['photoPopWeight'] || 10 + + // 判断是否为管理员 + isManager(res=>{ + this.setData({ + is_manager: res, }); - // 启动加载 - that.loadCat(); - // 是否开启上传功能 - - - checkCanUpload().then(res => { - that.setData({ - canUpload: res - }); - }) - }) + }, 3); // 先判断一下这个用户在12小时之内有没有点击过这只猫 if (!checkMultiClick(cat_id)) { @@ -129,14 +127,30 @@ Page({ } } }); + + // 开始加载页面 + const that = this; + getGlobalSettings('detailCat').then(settings => { + // 先把设置拿到 + page_settings = settings; + that.setData({ + photoPopWeight: settings['photoPopWeight'] || 10 + }); + // 启动加载 + that.loadCat().then(); + // 是否开启上传功能 + checkCanUpload().then(res => { + that.setData({ + canUpload: res + }); + }) + }); }, /** * 生命周期函数--监听页面显示 */ - onShow: function () { - - }, + onShow: function () {}, /** * 生命周期函数--监听页面隐藏 @@ -149,7 +163,11 @@ Page({ * 生命周期函数--监听页面卸载 */ onUnload: function () { - + console.log("page unload, context:", context); + if (context.cat_id) { + cat_id = context.cat_id; + album_raw = context.album_raw; + } }, /** @@ -183,27 +201,46 @@ Page({ } }, - loadCat() { + async loadCat() { const db = wx.cloud.database(); - db.collection('cat').doc(cat_id).get().then(res => { - console.log(res); - res.data.photo = []; - // res.data.characteristics_string = [(res.data.colour || '') + '猫'].concat(res.data.characteristics || []).join(','); - res.data.characteristics_string = (res.data.colour || '') + '猫'; - // res.data.nickname = (res.data.nickname || []).join('、'); + const cat = (await db.collection('cat').doc(cat_id).get()).data; + cat.photo = []; + cat.characteristics_string = (cat.colour || '') + '猫'; + cat.avatar = await getAvatar(cat._id, cat.photo_count_best); - this.setData({ - cat: res.data - }, ()=> { - this.reloadPhotos(); - this.loadCommentCount(); - var query = wx.createSelectorQuery(); - query.select('#info-box').boundingClientRect(); - query.exec((res) => { - console.log(res[0]); - infoHeight = res[0].height; - }) - }); + this.setData({ + cat: cat + }, ()=> { + this.reloadPhotos(); + this.loadCommentCount(); + this.loadRelations(); + var query = wx.createSelectorQuery(); + query.select('#info-box').boundingClientRect(); + query.exec((res) => { + console.log(res[0]); + infoHeight = res[0].height; + }) + }); + }, + + // 更新关系列表 + async loadRelations() { + var cat = this.data.cat; + var relations = this.data.cat.relations; + console.log(cat); + if (!cat._id || !relations) { + return false; + } + + for (var relation of relations) { + relation.cat = await getCatItem(relation.cat_id) + relation.cat.avatar = await getAvatar(relation.cat_id, relation.cat.photo_count_best); + } + + console.log(relations); + + this.setData({ + "cat.relations": relations, }); }, @@ -301,17 +338,9 @@ Page({ var photos = album_raw; } - // this.imgCompressedUrls = photos.map((photo) => { - // return (photo.photo_compressed || photo.photo_watermark || photo.photo_id); - // }); - // this.imgUrls = photos.map((photo) => { - // return (photo.photo_watermark || photo.photo_id); - // }); this.setData({ showGallery: true, - // imgUrls: this.imgUrls, galleryPhotos: photos, - // imgCompressedUrls: this.imgCompressedUrls, currentImg: this.currentImg, }); wx.hideLoading(); @@ -335,15 +364,7 @@ Page({ return; } - // this.imgCompressedUrls = photos.map((photo) => { - // return (photo.photo_compressed || photo.photo_watermark || photo.photo_id); - // }); - // this.imgUrls = photos.map((photo) => { - // return (photo.photo_watermark || photo.photo_id); - // }); this.setData({ - // imgCompressedUrls: this.imgCompressedUrls, - // imgUrls: this.imgUrls, galleryPhotos: photos, }); }, @@ -546,5 +567,21 @@ Page({ album_raw[current].like_count = like_count; this.updateAlbum(); } - } + }, + + toRelationCat(e) { + var cat_id = e.currentTarget.dataset.cat_id; + const url = `/pages/genealogy/detailCat/detailCat?cat_id=${cat_id}`; + wx.navigateTo({ + url: url, + }); + }, + + toAddRelation() { + var cat_id = this.data.cat._id; + const url = `/pages/manage/addRelations/addRelations?cat_id=${cat_id}`; + wx.navigateTo({ + url: url, + }); + }, }) \ No newline at end of file diff --git a/miniprogram/pages/genealogy/detailCat/detailCat.wxml b/miniprogram/pages/genealogy/detailCat/detailCat.wxml index 6f5c45b1..efd98ac8 100644 --- a/miniprogram/pages/genealogy/detailCat/detailCat.wxml +++ b/miniprogram/pages/genealogy/detailCat/detailCat.wxml @@ -5,190 +5,180 @@ - - - - - - - - - - - - - - - - {{cat.name}} - - - - - - - {{cat.popularity + (cat.photo_count_total? cat.photo_count_total * photoPopWeight: 0)}} - - - - {{cat.comment_count || 0}} - - + + + + - - {{adopt_desc[cat.adopt]}} - {{cat.sterilized? text_cfg.detail_cat.sterilized_true: text_cfg.detail_cat.sterilized_false}} - {{text_cfg.genealogy.to_star_tip}} - - {{text_cfg.detail_cat.button_feedback}} - - - - - - - - - {{text_cfg.detail_cat.label_nickname}} + + + + + + + + + + + {{cat.name}} + + + + + + + {{cat.popularity + (cat.photo_count_total? cat.photo_count_total * photoPopWeight: 0)}} - {{cat.nickname || '-'}} - - - - - {{text_cfg.detail_cat.label_location}} + + + {{cat.comment_count || 0}} - {{(cat.campus + cat.area) || '-'}} - - - - {{text_cfg.detail_cat.label_birthday}} + + + {{adopt_desc[cat.adopt]}} + {{cat.sterilized? text_cfg.detail_cat.sterilized_true: text_cfg.detail_cat.sterilized_false}} + {{text_cfg.genealogy.to_star_tip}} + + {{text_cfg.detail_cat.button_feedback}} + + - {{cat.birthday || '-'}} - - - - {{text_cfg.detail_cat.label_father}} + + + + + {{text_cfg.detail_cat.label_nickname}} + + {{cat.nickname || '-'}} - {{cat.father || '-'}} - - - - - {{text_cfg.detail_cat.label_mother}} + + + + {{text_cfg.detail_cat.label_location}} + + {{(cat.campus + cat.area) || '-'}} - {{cat.mother || '-'}} - - - - - {{text_cfg.detail_cat.label_friend}} + + + + {{text_cfg.detail_cat.label_birthday}} + + {{cat.birthday || '-'}} - {{cat.relation || '-'}} - - - - - - {{text_cfg.detail_cat.label_character}} + + + + + {{text_cfg.detail_cat.label_character}} + + + + {{(cat.characteristics || '') + (cat.characteristics.length?'\n':'') + (cat.habit || '-')}} + - - - {{(cat.characteristics || '') + (cat.characteristics.length?'\n':'') + (cat.habit || '-')}} + + + + + {{text_cfg.detail_cat.label_tutorial}} + + {{cat.tutorial || text_cfg.detail_cat.label_tutorial_empty}} - - - - - {{text_cfg.detail_cat.label_tutorial}} + + + + + 关系 + + + + + {{item.type}} + {{item.cat.name}} + + + + + + 添加关系 + + - {{cat.tutorial || text_cfg.detail_cat.label_tutorial_empty}} - - - - - - - - {{cat.name}}的相册 - 共{{albumMax}}张照片 - - - - - - {{photoOrderSelectorRange[photoOrderSelected][photoOrderSelectorKey]}} - - - + + + + + + {{cat.name}}的相册 + 共{{albumMax}}张照片 + + + + + + {{photoOrderSelectorRange[photoOrderSelected][photoOrderSelectorKey]}} + + + + - - - + \ No newline at end of file diff --git a/miniprogram/pages/genealogy/detailCat/detailCat.wxss b/miniprogram/pages/genealogy/detailCat/detailCat.wxss index 1e566cc6..6cd7b30f 100644 --- a/miniprogram/pages/genealogy/detailCat/detailCat.wxss +++ b/miniprogram/pages/genealogy/detailCat/detailCat.wxss @@ -427,4 +427,46 @@ swiper-item image { width: 20rpx; height: 20rpx; margin-right: 5rpx; +} + +/* 猫猫关系 */ +.relations { + width: 100%; + white-space: nowrap; +} +.relation-block { + width: 150rpx; + display: inline-flex; + flex-direction: column; + align-items: center; + padding: 10rpx 0; + border-radius: 20rpx; +} +.relation-block.tap { + background-color: var(--color-gray-light); +} +.relation-cat-avatar { + width: 100rpx; + height: 100rpx; + border-radius: 100%; + background-color: var(--color-white-dark); +} +.relation-name { + max-width: 100rpx; + margin-top: -20rpx; + font-size: 20rpx; + background-color: var(--color-primary-light); + padding: 5rpx 10rpx; + border-radius: 10rpx; + white-space: nowrap; + text-overflow:ellipsis; + overflow:hidden; +} +.relation-cat-name { + max-width: 150rpx; + font-size: 28rpx; + color: var(--color-primary-dark); + white-space: nowrap; + text-overflow:ellipsis; + overflow:hidden; } \ No newline at end of file diff --git a/miniprogram/pages/genealogy/genealogy.wxss b/miniprogram/pages/genealogy/genealogy.wxss index 59c70a99..8219a2b3 100644 --- a/miniprogram/pages/genealogy/genealogy.wxss +++ b/miniprogram/pages/genealogy/genealogy.wxss @@ -231,15 +231,12 @@ scroll-view { /* 广告栏 */ .card-ad { - /* margin: 20rpx 67.5rpx 50rpx 67.5rpx; */ margin: 15rpx 0; width: 635rpx; border-radius: 15rpx; background-color: white; box-shadow: 13rpx 13rpx 30rpx var(--color-gray); overflow: hidden; - /* overflow: visible; */ - /* flex-grow: 1; */ display: flex; justify-content: center; diff --git a/miniprogram/pages/info/devTeam/devTeam.js b/miniprogram/pages/info/devTeam/devTeam.js index 03279dbf..5e4b710f 100644 --- a/miniprogram/pages/info/devTeam/devTeam.js +++ b/miniprogram/pages/info/devTeam/devTeam.js @@ -12,6 +12,19 @@ Page({ text_cfg: text_cfg, github_link: "https://github.com/sysucats/zhongdamaopu", update_log: [{ + version: "v1.8.3", + content: [ + "优化管理页面", + ], + time: "2022/07/06" + }, { + version: "v1.8.2", + content: [ + "新增猫猫关系", + "代码质量" + ], + time: "2022/07/02" + }, { version: "v1.8.1", content: [ "管理员审核照片更顺手啦", diff --git a/miniprogram/pages/info/info.wxml b/miniprogram/pages/info/info.wxml index 063c3bcc..d7b4ebed 100644 --- a/miniprogram/pages/info/info.wxml +++ b/miniprogram/pages/info/info.wxml @@ -33,6 +33,10 @@ 反馈处理({{numFeedbacks}}) + + 管理猫猫关系 + + 创建公告 diff --git a/miniprogram/pages/manage/addRelations/addRelations.js b/miniprogram/pages/manage/addRelations/addRelations.js new file mode 100644 index 00000000..1b083ebf --- /dev/null +++ b/miniprogram/pages/manage/addRelations/addRelations.js @@ -0,0 +1,418 @@ +// 审核照片 +const utils = require('../../../utils.js'); +const isManager = utils.isManager; +const regReplace = utils.regReplace; + +const cat_utils = require('../../../cat.js'); +const getAvatar = cat_utils.getAvatar; +const getCatItem = cat_utils.getCatItem; + +const db = wx.cloud.database(); +const _ = db.command; + +// 运行状态 +var selectRelationTypeIdx = undefined; +var selectRelationCatIdx = undefined; + +Page({ + + /** + * 页面的初始数据 + */ + data: { + cat: {}, + relation_types: [], + filters_input: "", + + // 控制底部栏是否弹出 + showSearchCat: false, + showSearchType: false, + }, + + /** + * 生命周期函数--监听页面加载 + */ + onLoad(options) { + this.checkAuth(); + var that = this; + if (options.cat_id) { + // 输入了cat_id + db.collection('cat').doc(options.cat_id).get().then(res => { + var cat = res.data; + getAvatar(cat._id, cat.photo_count_best).then(avatar => { + cat.avatar = avatar; + that.setData({ + cat: cat + }, () => { + that.loadRelations(); + }); + }); + }) + } else { + setTimeout(function() { + that.bindSearch(null, "cat"); + }, 700); + } + }, + + // 检查权限 + checkAuth() { + const that = this; + isManager(function (res) { + if (res) { + that.setData({ + auth: true + }); + that.loadRelationTypes(); + } else { + that.setData({ + tipText: '只有管理员Level-2能进入嗷', + tipBtn: true, + }); + console.log("Not a manager."); + } + }, 2) + }, + + /** + * 生命周期函数--监听页面初次渲染完成 + */ + onReady() { + + }, + + /** + * 生命周期函数--监听页面显示 + */ + onShow() { + + }, + + /** + * 生命周期函数--监听页面隐藏 + */ + onHide() { + + }, + + /** + * 生命周期函数--监听页面卸载 + */ + onUnload() { + + }, + + /** + * 页面相关事件处理函数--监听用户下拉动作 + */ + onPullDownRefresh() { + + }, + + /** + * 页面上拉触底事件的处理函数 + */ + onReachBottom() { + + }, + + // 加载setting里的relation types + async loadRelationTypes() { + var types = []; + var data = (await db.collection('setting').where({_id: 'relation'}).get()).data; + console.log(data); + if (data.length == 0) { + // 当数据库setting中不存在时,进行初始化 + types = ["爸爸", "妈妈"] + await db.collection('setting').doc('relation').set({ + data: { + types: types, + } + }); + } else { + types = data[0].types; + } + + this.setData({ + relation_types: types, + }); + }, + + // 保存新的关系类型 + async saveNewRelationType(e) { + console.log(e); + const t = e.detail.value; + var types = this.data.relation_types; + + // 判断一下是否已存在 + var idx = types.indexOf(t); + if (idx == -1) { + // 不存在 + types.push(t); + console.log(types); + await wx.cloud.callFunction({ + name: "relationOp", + data: { + type: "saveRelationTypes", + relationTypes: types, + } + }); + idx = types.length - 1; + } + + this.selectRelationType(null, idx); + + this.setData({ + relation_name: "", + relation_types: types, + }); + }, + + selectRelationType(e, idx) { + if (idx === undefined) { + idx = e.currentTarget.dataset.index; + } + var type = this.data.relation_types[idx]; + console.log(type); + this.setData({ + [`cat.relations[${selectRelationTypeIdx}].type`]: type, + showSearchCat: false, + showSearchType: false, + }); + }, + + async deleteRelationType(e) { + var idx = e.currentTarget.dataset.index; + var types = this.data.relation_types; + const that = this; + wx.showModal({ + title: '提示', + content: `确定删除\"${types[idx]}\"关系?`, + success(res) { + if (res.confirm) { + that.doDeleteRelationType(idx); + } + } + }) + }, + + async doDeleteRelationType(idx) { + var types = this.data.relation_types; + types.splice(idx, 1); + await wx.cloud.callFunction({ + name: "relationOp", + data: { + type: "saveRelationTypes", + relationTypes: types, + } + }); + this.setData({ + relation_name: "", + relation_types: types, + }); + }, + + bindSearch(e, type) { + if (!type) { + type = e.currentTarget.dataset.type; + } + + var that = this; + var fCat, fType; + if (type == "cat") { + selectRelationCatIdx = e ? e.currentTarget.dataset.index: undefined; + fCat = true; + fType = false; + } else if (type == "relation") { + selectRelationTypeIdx = e ? e.currentTarget.dataset.index: undefined; + fCat = false; + fType = true; + } else if (type == "hide") { + fCat = false; + fType = false; + } + this.setData({ + showSearchCat: fCat, + showSearchType: fType, + }); + setTimeout(()=>{ + that.setData({ + focusSearchCat: fCat, + }); + }, 400); + }, + + // 搜索猫猫 + fSearchInput(e) { + var value = e.detail.value; + this.setData({ + filters_input: value + }) + }, + + async doSearchCat() { + if (!this.data.filters_input) { + return false; + } + wx.showLoading({ + title: '搜索中...', + }) + var filters = []; + const filters_input = regReplace(this.data.filters_input); + if (filters_input.length) { + var search_str = []; + for (const n of filters_input.trim().split(' ')) { + search_str.push(`(.*${n}.*)`); + } + let regexp = db.RegExp({ + regexp: search_str.join("|"), + options: 'igs', + }); + filters.push(_.or([{ + name: regexp + }, { + nickname: regexp + }])); + } + + // 准备搜索 + var query = filters.length ? _.and(filters) : {}; + var cats = (await db.collection('cat').where(query).get()).data; + // 获取头像 + for (var cat of cats) { + cat.avatar = await getAvatar(cat._id, cat.photo_count_best); + } + this.setData({ + searchCats: cats, + }); + wx.hideLoading(); + }, + // 选择猫猫 + searchSelectCat(e) { + var idx = e.currentTarget.dataset.index; + var cat = this.data.searchCats[idx]; + if (selectRelationCatIdx === undefined) { + this.data.cat = cat; + this.setData({ + cat: cat, + showSearchCat: false, + }); + this.loadRelations(); + return; + } + + this.setData({ + [`cat.relations[${selectRelationCatIdx}].cat_id`]: cat._id, + [`cat.relations[${selectRelationCatIdx}].cat`]: cat, + showSearchCat: false, + showSearchType: false, + }); + }, + // 更新关系列表 + async loadRelations() { + var cat = this.data.cat; + var relations = this.data.cat.relations; + console.log(cat); + if (!cat._id || !relations) { + return false; + } + + for (var relation of relations) { + if (!relation.cat_id) { + continue; + } + relation.cat = await getCatItem(relation.cat_id) + relation.cat.avatar = await getAvatar(relation.cat_id, relation.cat.photo_count_best); + } + + console.log(relations); + + this.setData({ + "cat.relations": relations, + }); + }, + // 新增一个关系 + addRelation(e) { + var relations = this.data.cat.relations; + if (relations === undefined) { + relations = []; + } + relations.push({}); + this.setData({ + "cat.relations": relations + }); + }, + // 关系列表操作 + bindRelationTap(e) { + var type = e.currentTarget.dataset.type; + var idx = e.currentTarget.dataset.index; + var relations = this.data.cat.relations; + + if (type == "delete") { + relations.splice(idx, 1); + } else if (type == "up" && idx != 0) { + var tmp = relations[idx-1]; + relations[idx-1] = relations[idx]; + relations[idx] = tmp; + } else if (type == "down" && idx != relations.length-1) { + var tmp = relations[idx+1]; + relations[idx+1] = relations[idx]; + relations[idx] = tmp; + } + this.setData({ + "cat.relations": relations + }); + }, + // 保存关系列表 + async saveRelations() { + if (!await this.checkSaveRelations()) { + return false; + } + + wx.showLoading({ + title: '保存中...', + }); + + var cat = this.data.cat; + var relations = []; + for (const r of cat.relations) { + relations.push({ + type: r.type, + cat_id: r.cat_id, + }); + } + await wx.cloud.callFunction({ + name: "relationOp", + data: { + type: "saveRelation", + cat_id: cat._id, + relations: relations, + } + }); + + wx.showToast({ + title: '保存成功', + }); + }, + + async checkSaveRelations() { + var cat = this.data.cat; + if (!cat._id) { + return false; + } + + for (let i = 0; i < cat.relations.length; i++) { + const r = cat.relations[i]; + console.log(r); + if (!r.type || !r.cat_id) { + wx.showToast({ + title: `#${i+1}号关系不完整~`, + icon: "error" + }); + return false; + } + } + + return true; + } +}) \ No newline at end of file diff --git a/miniprogram/pages/manage/addRelations/addRelations.json b/miniprogram/pages/manage/addRelations/addRelations.json new file mode 100644 index 00000000..8835af06 --- /dev/null +++ b/miniprogram/pages/manage/addRelations/addRelations.json @@ -0,0 +1,3 @@ +{ + "usingComponents": {} +} \ No newline at end of file diff --git a/miniprogram/pages/manage/addRelations/addRelations.wxml b/miniprogram/pages/manage/addRelations/addRelations.wxml new file mode 100644 index 00000000..946d5d74 --- /dev/null +++ b/miniprogram/pages/manage/addRelations/addRelations.wxml @@ -0,0 +1,77 @@ + + + + + + {{cat.name || "选择猫猫"}} + + {{cat.campus +" "+ cat.area}} + [旧数据] 父亲:{{cat.father||'-'}},母亲:{{cat.mother||'-'}},好友:{{cat.friend||'-'}} + + + + + + #{{index+1}} + {{item.type || '选择关系'}} + + + {{item.cat.name || '点击选择猫猫'}} + + + 删除 + + + + + + + + 新增一条关系 + + + 请先选择猫猫 + + + + + + + + + + + + + + + + {{item.name}} + {{item.campus}} {{item.area}} + + + 请搜索后进行选择 + + + + + + + + + + + + {{item}} + + 选择 + 删除 + + + + + + + + {{tipText}} + + \ No newline at end of file diff --git a/miniprogram/pages/manage/addRelations/addRelations.wxss b/miniprogram/pages/manage/addRelations/addRelations.wxss new file mode 100644 index 00000000..6379c82c --- /dev/null +++ b/miniprogram/pages/manage/addRelations/addRelations.wxss @@ -0,0 +1,207 @@ +/* pages/manage/relations/addRelations/addRelations.wxss */ +@import "../../genealogy/genealogy.wxss"; +@import "../checkPhotos/checkPhotos.wxss"; + +page { + padding: 20rpx 0 0 0; + background-color: transparent; +} + +/* 上方处理部分 */ +.relation { + width: 100%; + padding: 10rpx 30rpx; + box-sizing: border-box; + display: flex; + align-items: center; + justify-content: space-between; +} + +.relation-index { + font-size: 22rpx; + font-weight: lighter; + color: var(--color-black-min); +} + +.relation-name { + width: 130rpx; + padding: 10rpx 20rpx; + font-size: 24rpx; + background-color: var(--color-primary-light); + white-space: nowrap; + text-overflow:ellipsis; + overflow:hidden; + text-align: center; +} +.relation-name.tap { + background-color: var(--color-primary); +} + +.relation-cat { + width: 120rpx; + height: 120rpx; + display: flex; + flex-wrap: wrap; + justify-content: center; +} +.relation-cat.tap { + background-color: var(--color-gray-light); +} + +.relation-cat-avatar { + width: 100rpx; + height: 100rpx; + background-color: var(--color-gray-dark); + border-radius: 100%; +} + +.relation-cat-name { + font-size: 24rpx; + margin-top: -30rpx; + width: 120rpx; + text-align: center; + white-space: nowrap; + text-overflow:ellipsis; + overflow:hidden; + background-color: var(--color-white-dark); + border: 2rpx solid var(--color-primary); +} + +.buttons .button { + font-size: 20rpx; + white-space: nowrap; + transition: background-color 200ms ease, border-color 200ms ease, color 200ms ease; +} +.buttons .button.disabled { + color: var(--color-gray-dark); + background-color: var(--color-gray-light); +} +/* 添加一组 */ +.relation.add { + border: 3rpx dashed var(--color-gray-dark); + margin: 20rpx 30rpx; + border-radius: 15rpx; + text-align: center; + font-size: 28rpx; + color: var(--color-primary-dark); + width: 690rpx; +} +/* 保存 */ +.primary { + width: 690rpx; + margin: 0 30rpx; +} + +/* 底部搜索猫猫 */ +.search-mask { + background-color: var(--color-black-transparent); + width: 100%; + height: 100vh; + position: absolute; + top: 0; +} +#search { + position: absolute; + bottom: 0; + padding: 20rpx 20rpx; + padding-bottom: max(20rpx, constant(safe-area-inset-bottom)); + padding-bottom: max(20rpx, env(safe-area-inset-bottom)); + display: block; + + /* border-top: 5rpx solid var(--color-primary); */ + border-top-left-radius: 50rpx; + border-top-right-radius: 50rpx; + + overflow: hidden; + box-sizing: border-box; + transition: height 200ms ease, bottom 200ms ease; +} + +#search.hidden { + padding: 0; + bottom: -700rpx; +} + +#search .search-logo { + background-color: transparent; +} + +#search .input-block { + width: 100%; + height: 100rpx; + margin: 10rpx 0; +} + +#search .search-results { + width: 100%; + height: 400rpx; +} + +.search-empty { + width: 100%; + text-align: center; + color: var(--color-gray-dark); + font-size: 24rpx; +} + +.search-cat { + width: 100%; + height: 100rpx; + padding: 15rpx; + display: flex; + border-bottom: 1rpx solid var(--color-gray); + align-items: center; + box-sizing: border-box; +} + +.search-cat-click { + background-color: var(--color-gray); +} + +.search-cat-avatar { + width: 60rpx; + height: 60rpx; + border-radius: 100%; + background-color: lightgray; +} + +.search-cat-info { + height: 60rpx; + margin-left: 20rpx; + display: flex; + align-items: center; +} + +.search-cat-name { + font-size: 34rpx; + color: var(--color-primary-dark); +} + +.search-cat-position { + font-size: 24rpx; + padding: 0 10rpx; + color: var(--color-black-light); +} + +/* 底部搜关系名 */ +.search-relation-item { + width: 100%; + display: flex; + flex-wrap: nowrap; + white-space: nowrap; + justify-content: space-between; + align-items: center; + margin: 10rpx 0; + border-bottom: 2rpx solid var(--color-gray-light); +} + +.search-relation-name { + font-size: 28rpx; + color: var(--color-black-min); +} + +/* 旧数据 */ +.old-data { + font-size: 20rpx; + color: var(--color-gray-dark); +} \ No newline at end of file diff --git a/miniprogram/pages/manage/checkPhotos/checkPhotos.js b/miniprogram/pages/manage/checkPhotos/checkPhotos.js index 3c595299..30252ff9 100644 --- a/miniprogram/pages/manage/checkPhotos/checkPhotos.js +++ b/miniprogram/pages/manage/checkPhotos/checkPhotos.js @@ -150,8 +150,15 @@ Page({ campus_list[campus].push(photo); } + // 恢复最后一次审批的校区 + var cache_active_campus = cache.getCacheItem("checkPhotoCampus"); + if (!cache_active_campus || !campus_list[cache_active_campus]) { + cache_active_campus = undefined + } + this.setData({ campus_list: campus_list, + active_campus: cache_active_campus, }) wx.hideLoading(); @@ -268,7 +275,10 @@ Page({ that.doCheckMulti(); } } - }) + }); + + // 记录一下最后一次审批的cache + cache.setCacheItem("checkPhotoCampus", active_campus, 24*7*31); }, // 开始批量处理 diff --git a/miniprogram/pages/manage/checkPhotos/checkPhotos.wxml b/miniprogram/pages/manage/checkPhotos/checkPhotos.wxml index d79b9da2..3b5dde6d 100644 --- a/miniprogram/pages/manage/checkPhotos/checkPhotos.wxml +++ b/miniprogram/pages/manage/checkPhotos/checkPhotos.wxml @@ -5,11 +5,13 @@ - 点击校区名展示待审核照片列表。\n先逐张标记处理方式,再点击“批量审核”。\n图片可以放大,点击名字跳转猫猫详情。\n每次展示前20张,注意流量消耗哈。 - + 先逐张标记处理方式,再点击“批量审核”。\n图片可以放大,点击名字跳转猫猫详情。\n每次展示前20张,注意流量消耗哈。 + {{index}}({{item.length}}) - + + 没有待审核的照片啦~ + 请在上方选择一个校区 diff --git a/miniprogram/pages/manage/checkPhotos/checkPhotos.wxss b/miniprogram/pages/manage/checkPhotos/checkPhotos.wxss index 1e134551..fdf28887 100644 --- a/miniprogram/pages/manage/checkPhotos/checkPhotos.wxss +++ b/miniprogram/pages/manage/checkPhotos/checkPhotos.wxss @@ -134,15 +134,28 @@ image { /* 校区选择器 */ .campus-list { width: 100%; - white-space: nowrap; } .campus { display: inline-block; - margin: 10rpx 30rpx; + margin: 10rpx 10rpx; + padding: 0 10rpx; color: var(--color-black-min); + border: 3rpx solid transparent; + border-radius: 15rpx; + font-size: 28rpx; } .campus.active { - font-weight: bold; + /* font-weight: bold; */ + border-left: 3rpx solid var(--color-primary); + border-right: 3rpx solid var(--color-primary); +} + +/* 提示选择 */ +.tip { + width: 100%; + font-size: 24rpx; + color: var(--color-gray-dark); + text-align: center; } \ No newline at end of file diff --git a/miniprogram/pages/manage/managers/managers.js b/miniprogram/pages/manage/managers/managers.js index 76efbcf2..a2b0c666 100644 --- a/miniprogram/pages/manage/managers/managers.js +++ b/miniprogram/pages/manage/managers/managers.js @@ -17,7 +17,7 @@ Page({ managerOnly: false, users: [], windowHeight: "300", - manager_types: ['0-非管理员', '1-审核照片、删除留言', '2-修改猫猫、校区', '3-处理图片', '99-管理成员'] + manager_types: ['0-非管理员', '1-审核照片、删除留言', '2-修改猫猫、校区、关系', '3-处理图片、发布公告', '99-管理成员'] }, /** * 生命周期函数--监听页面加载 diff --git a/miniprogram/pages/news/detailNews/detailNews.js b/miniprogram/pages/news/detailNews/detailNews.js index dddf02b5..80f1a408 100644 --- a/miniprogram/pages/news/detailNews/detailNews.js +++ b/miniprogram/pages/news/detailNews/detailNews.js @@ -1,7 +1,4 @@ // pages/news/detailNews/detailNews.js -const { - keys -} = require('../../../packages/regenerator-runtime/runtime.js'); const utils = require('../../../utils.js'); const isManager = utils.isManager; const shareTo = utils.shareTo; diff --git a/miniprogram/user.js b/miniprogram/user.js index 31e0fdc3..531a0c32 100644 --- a/miniprogram/user.js +++ b/miniprogram/user.js @@ -1,5 +1,4 @@ // 负责用户表的管理、使用接口 -import { async } from './packages/regenerator-runtime/runtime.js'; import { randomInt, userInfoEq } from './utils.js'; // 获取当前用户 diff --git a/miniprogram/utils.js b/miniprogram/utils.js index c4bd3995..a7ddb69c 100644 --- a/miniprogram/utils.js +++ b/miniprogram/utils.js @@ -1,9 +1,5 @@ -const regeneratorRuntime = require('./packages/regenerator-runtime/runtime.js'); - const sha256 = require('./packages/sha256/sha256.js'); -// import regeneratorRuntime from './packages/regenerator-runtime/runtime.js'; - function randomInt(min, max) { return Math.floor(Math.random() * (max - min)) + min; } @@ -263,7 +259,6 @@ function checkDeploy() { module.exports = { - regeneratorRuntime, sha256, randomInt, generateUUID, diff --git a/project.config.json b/project.config.json index a73d3d11..9e90625e 100644 --- a/project.config.json +++ b/project.config.json @@ -156,16 +156,11 @@ "scene": null }, { - "name": "单页模式猫谱(分享到朋友圈)", - "pathName": "pages/genealogy/genealogy", - "query": "", - "scene": 1154 - }, - { - "name": "单页模式关于页", - "pathName": "pages/info/info", + "name": ">>>部署指引<<<", + "pathName": "pages/debug/deployTip/deployTip", "query": "", - "scene": 1154 + "launchMode": "default", + "scene": null } ] }