1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/d718781500-student_product_manager_system

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
Внести вклад в разработку кода
Синхронизировать код
Отмена
Подсказка: Поскольку Git не поддерживает пустые директории, создание директории приведёт к созданию пустого файла .keep.
Loading...
readme.md

Текст запроса:

微信扫码登入 (new)

Описание процесса входа в систему с помощью сканирования QR-кода через приложение WeChat.

В тексте описаны:

  • процесс установки необходимых зависимостей;
  • события socket.io;
  • интерфейсы для работы с системой: получения QR-кодов, входа через WeChat, выхода из системы, загрузки аватара пользователя, проверки состояния входа, изменения пароля и получения списка пользователей.

Установка необходимых зависимостей

Для реализации входа с использованием WeChat рекомендуется использовать зависимость socket.io-client@2.3.0. Для этого необходимо выполнить следующую команду:

npm i socket.io-client

Также можно использовать обычный WebSocket.

События socket.io

Событие Возвращаемый параметр Описание параметра
connectSuccess sid Уникальный идентификатор клиента
invalidCode Object Недействительный код
scancodeSuccess wechatCode Временный код, возвращаемый после сканирования QR-кода

Интерфейсы

Получение URL QR-кода

Интерфейс Метод запроса Передаваемые параметры Обязательность параметров Описание интерфейса
/users/getQrcode get sid Да Запрос адреса QR-кода для входа

Вход через WeChat

Интерфейс Метод запроса Описание интерфейса
/users/wechatLogin get Запрос на вход через WeChat
Параметр Обязательность Описание
wechatCode Да Код, полученный после успешного сканирования QR-кода

Процесс входа через WeChat

Выход из системы

Интерфейс Метод запроса Адрес интерфейса
Выход из системы get /users/sigout

Загрузка аватара пользователя

Интерфейс Метод запроса Адрес интерфейса
Загрузка аватара post /users/uploadAvatar
Параметры Обязательность Описание
headimgurl Да Загружаемая картинка
unid Да Идентификатор текущего пользователя
token Да Токен (можно передать в заголовке запроса, поле authorzation)

Успешный ответ:

{
    "status": 1,
    "state": true,
    "msg": "Картинка загружена успешно",
    "imgurl": "https://chst.vip/imgs/headimgurl-1650792836990.png"
}

Проверка состояния входа

Интерфейс Метод запроса Адрес интерфейса
Проверка состояния входа * /verify

Изменение пароля

Интерфейс Метод запроса Адрес интерфейса
Изменение пароля post /users/updatePassword
Параметры Обязательность Описание
username Да Имя пользователя
oldPassword Да Старый пароль
newPassword Да Новый пароль
token Да Токен

Ответ при успешном изменении пароля:

{
  "status": 1,
  "state": true,
  "msg": "Пароль изменён успешно"
}

При отсутствии пользователя в системе:

{
  "status": 0,
  "state": false,
  "msg": "Пользователь не найден"
}

При неудачной попытке изменения пароля:

{
  "status": 0,
  "state": false,
  "msg": "Ошибка при изменении пароля"
}

Получение списка всех пользователей

Интерфейс Метод запроса Адрес интерфейса
Получение списка пользователей get /users/getAllUsers

Пример ответа:

{
    "status": 200,
    "state": true,
    "msg": "success",
    "users": [
        {
            "username": "lbw1",
            "nickname": "五五开",
            "roleid": "200"
        },
        {
            "username": "root",
            "nickname": "王者管理员",
            "roleid": "1"
        }
    ]
}

Добавление пользователя

Интерфейс Метод запроса Адрес интерфейса
Добавление пользователя post /users/addUser

Обязательные параметры:

  • username — имя пользователя;
  • password — пароль;
  • nickname — никнейм.

Необязательный параметр:

  • phone — номер телефона.

Обновление информации о пользователе

Интерфейс Метод запроса Адрес интерфейса
Обновление информации о пользователе post /users/updateUser

Параметры:

  • unid — идентификатор пользователя;
  • username (необязательно) — имя пользователя. Таблица 1. Регистрация пользователя | Поле | Обязательное | Описание | | :--: | :--: | :--:| | username | Да | Имя пользователя | | password | Да | Пароль | | phone | Нет | Номер телефона | | nickname | Да | Никнейм | | roles | Нет | Права доступа |

Таблица 2. Интерфейс регистрации пользователя (устаревший)

Описание Метод запроса Адрес
Регистрация пользователя POST /users/register
Параметр Обязательное поле Описание
username Да Имя пользователя
password Да Пароль
phone Нет Телефон
nickname Да Никнейм
roles Нет Права доступа

Результат успешной регистрации:

{
    "status": 1,
    "state": true,
    "msg": "Регистрация прошла успешно",
    "userInfo": {
        "username": "lbw4",
        "nickname": "Не буду читерить вечно",
        "phone": "1577775772"
    }
}

Результат неудачной регистрации:

{
    "status": 0,
    "state": false,
    "msg": "Имя пользователя уже занято"
}

Модуль разрешений

Добавление роли (только для root)

Описание Метод запроса Адрес
Добавление роли POST /permission/addrole
Параметр Обязательное поле Описание
roleid Да Идентификатор добавляемой роли
token Да Токен

Получение списка ролей

Описание Метод запроса Адрес
Получение списка ролей GET /permission/getrole
Параметр Обязательное поле Описание
roleid Нет Идентификатор роли для поиска
token Да Токен
Результат:
{
  "status": 200,
  "msg": "success",
  "roles": [
    {
      "roleid": "200",
      "roleName": "Сотрудник"
    },
    {
      "roleid": "102",
      "roleName": "Директор"
    },
    {
      "roleid": "103",
      "roleName": "Руководитель"
    },
    {
      "roleid": "1",
      "roleName": "Администратор"
    }
  ]
}

Получение меню разрешений

Описание Метод запроса Адрес
Получение меню разрешений GET /permission/getMenuList
{
  "status": 200,
  "msg": "успех",
  "roleName": "директор",
  "menuList": [
    {
      "name": "Главная страница управления"
    },
    {
      "name": "Управление учениками",
      "children": [
        {
          "name": "Ученические проекты"
        },
        {
          "name": "Личные данные учеников"
        },
        {
          "name": "Общежития учеников"
        }
      ]
    },
    {
      "name": "Контроль посещаемости"
    },
    {
      "name": "Статистические данные"
    },
    {
      "name": "Мой центр"
    }
  ]
}

VIP-пополнение

1. Получение информации о продуктах VIP

Адрес Метод запроса Описание интерфейса
/product/get_product GET Получение товаров
Параметр Значение параметра Обязательное поле
category_id 20210827165510715 Да

Результат:

[
  {
    "updator": null,
    "updateTime": null,
    "_id": "61277523ad0bdb2ddd70a304",
    "product_id": "20210826190403911",
    "category_id": "20210826182431225",
    "productName": "VIP-пополнение",
    "description": "Эксклюзивный пакет VIP-услуг: VIP-пополнение, VIP-удовольствие, личный консьерж 1:1, неограниченный доступ, неограниченное количество жалоб, эксклюзивное VIP-имя",
    "price": 0.01,
    "inventory": 74,
    "imageUrl": "balabalabala"
  }
]

2. Оформление заказа

Адрес Метод запроса Описание интерфейса
/order/pre_order POST Предварительное оформление заказа
Параметр Описание Обязательное поле
product_id Идентификатор товара Да
quantity Количество товара Нет

Результат:

{
  "status": 200,
  "state": true,
  "order_id": "20210830105149117IhPOnp541908",
  "msg": "Оформление заказа прошло успешно"
}

3. Запуск оплаты

Адрес Метод запроса Описание интерфейса
/pay/payment POST Запуск оплаты

В запросе не указаны параметры. 4. Запрос результатов оплаты

/order/query_order_status get 用户必须是 в состоянии входа Запрос состояния оплаты заказа (можно опрашивать)
Параметры Нужно ли передавать Описание параметров
order_id Да Идентификатор заказа
  if (result[0].pay_status === 1) {
            res.send({ status: 200, state: true, msg: "Оплата прошла успешно" })
            return
        } else if (result[0].order_status === 2) {
            res.send({ status: 3002, state: false, msg: "Заказ отменён" })
            return
        } else if (result[0].order_status === 3) {
            res.send({ status: 3003, state: false, msg: "Недействительный заказ" })
            return
        } else if (result[0].order_status === 4) {
            res.send({ status: 3004, state: false, msg: "Транзакция закрыта" })
            return
        }else {
            res.send({ status: 3005, state: false, msg: "Ещё не оплачено" })
        }

7. Модуль магазина

5.1 Модуль категорий

5.1.1 Добавление категории

Адрес интерфейса Метод запроса Интерфейс описания
/category/addCategory post Добавление категории товаров
Параметры Описание параметров Нужно ли передавать
categoryName Название категории (String) Да
categoryImgurl Изображение категории Нет

Ответ успешный

{
    "status": 200,
    "state": true,
    "msg": "Добавление прошло успешно"
}

Ответ на неудачный результат

{
    "status": 1004,
    "state": false,
    "msg": "Категория уже существует, пожалуйста, не добавляйте повторно"
}

5.1.2 Удаление категории (использовать с осторожностью)

Поскольку категория и товар связаны, удаление может привести к неправильному получению товара по категории.

Адрес интерфейса Метод запроса Интерфейс описания
/category/delCategory get Удаление категории
Параметры Метод запроса Интерфейс описания
category_id get Идентификатор категории

Ответ успешный результат

{
    "status": 200,
    "state": true,
    "msg": "Удаление прошло успешно"
}

Ответ на неудачный результат

{
    "status": 1004,
    "state": false,
    "msg": "err Данные не существуют"
}

5.1.3 Изменение категории

Адрес интерфейса Метод запроса Интерфейс описания
/category/updateCategory post Удаление категории
Параметры Характеристика Нужно ли передавать
categoryName Название категории Да
category_id Идентификатор категории Да

5.1.4 Получение категории

Адрес запроса

/category/getCategory

Ответ успешный результат

{
    "status": 200,
    "state": true,
    "msg": "Получение прошло успешно",
    "data": [
        {
            "updateTime": null,
            "updator": null,
            "_id": "5fed5acfb308240d6037bc13",
            "category_id": "20201231125959413",
            "categoryName": "Транспортные средства",
            "creator": "lbw",
            "createTime": "2020-12-31,12:59:59"
        },
        {
            "updateTime": null,
            "updator": null,
            "_id": "5fed5c45b308240d6037bc19",
            "category_id": "20201231130613547",
            "categoryName": "Косметика",
            "creator": "lbw",
            "createTime": "2020-12-31,01:06:13"
        }
    ]
}

5.2 Модуль товаров

5.2.1 Добавление информации о товаре

Адрес интерфейса Метод запроса Интерфейс описания
/product/add_product post Добавление товара
Параметры Характеристика Нужно ли передавать
category_id Цель категории (String) Да
productName Название товара (String) Да
price Цена товара (Number) Единица измерения — юань Да
description Описание товара (String) Да
inventory Количество товара на складе (Number) Да
imageUrl Изображение товара (file) Загрузить изображение товара Да

5.2.2 Изменение информации о товаре

Адрес интерфейса Метод запроса Интерфейс описания
/product/update_product post Изменение информации о товаре
Параметры Характеристика Нужно ли передавать
product_id Идентификатор товара (String) Да
productName Название товара (String) Нет
price Цена товара (Number) Единица измерения — юань 5.2.3 Получение информации о товаре
Интерфейс Метод Описание интерфейса
/product/get_product GET Получение информации о товаре
Параметр Описание Обязательно
product_id Идентификатор товара, по умолчанию возвращается вся информация, если не передан Нет
category_id Категория товара Нет

5.2.4 Удаление товара

Интерфейс Метод Описание интерфейса
/product/del_product GET Удаление информации о товаре
Параметр Описание Обязательно
product_id Идентификатор товара Да

5.3 Модуль корзины покупок

5.3.1 Выбор товара в корзине покупок

Интерфейс Метод Параметры Описание интерфейса
/cart/check POST product_id Передаётся идентификатор товара. Если выбрано несколько товаров, можно передать их через запятую, например: {product_id:"1198,16843,19894"}

5.3.2 Получение данных корзины покупок

Интерфейс Метод Описание интерфейса
/cart/get_cart GET Получение текущих данных пользователя в корзине покупок

5.3.3 Удаление товара из корзины покупок

Интерфейс Метод Описание интерфейса
/cart/del_prouct GET Удаление товара из корзины покупок
Параметры Обязательно Описание
product_id Да Идентификатор удаляемого товара

5.3.4 Обновление данных корзины покупок

Интерфейс Метод Описание интерфейса
/cart/update_cart POST Изменение количества товаров и других параметров в корзине покупок
Параметры Обязательно Описание
product_id Да Изменяемый товар
count Да Количество товара

5.3.5 Добавление товара в корзину покупок

Интерфейс Метод Описание интерфейса
/cart/add_to_cart POST Добавление товара в корзину покупок
Параметры Обязательно Описание
product_id Да Товар для добавления
count Да Количество добавляемого товара

5.4 Модуль заказов

5.4.1 Создание предварительного заказа (заказ автоматически аннулируется через 2 минуты)

Интерфейс Метод Параметры Описание интерфейса
/pay/pre_order POST Отправка предварительного заказа
Параметры Обязательность Описание
product_id Нет Идентификатор продукта
quantity Нет Количество приобретаемых продуктов

Состояние заказа

  • order_status: состояние заказа: 0 — не отправлен, 1 — успешно отправлен, 2 — отменён, 3 — недействительный заказ, 4 — закрытая сделка, 5 — возврат.

Статус оплаты заказа

  • pay_status: 0 — неоплаченный, 1 — оплаченный.

Статус доставки заказа

  • shiping_status: статус доставки: 0 — доставка не начата, 1 — доставка началась, 2 — доставка завершена, 3 — товар в наличии.

5.4.2 Запрос статуса оплаты заказа

Интерфейс Метод Параметры Описание интерфейса
/order/query_order_status GET Запрос статуса оплаты заказа (можно повторять)
Параметры Обязательность Описание
order_id Да Идентификатор заказа

5.4.3 Запрос подробной информации о заказе

Можно запрашивать статус оплаты заказа, повторяя запрос. Необходимо указать идентификатор заказа.

Интерфейс Метод Описание интерфейса
/order/get_order POST Запрос текущего статуса заказа пользователя
Параметры Обязательность Описание
order_id Нет Можно получить информацию об отдельном заказе. По умолчанию возвращаются все заказы

5.4.4 Отмена заказа (в разработке)

Интерфейс Метод Параметры Описание интерфейса
/order/cancel GET order_id Отмена текущего заказа

5.4.5 Удаление заказа

Интерфейс Метод Параметры Описание интерфейса
/order/del_order GET order_id Удаление указанного заказа

5.4.6 Отправка заказа (в разработке)

Интерфейс Метод Параметры Описание интерфейса
/order/ship GET Доставка заказа
Интерфейс Метод Описание
/order/returns post Возврат товара

Параметры:

Параметр Описание Обязательно
order_id Номер заказа Да

8. Оплата

6.1. Оплата с помощью сканирования QR-кода через WeChat Pay

Интерфейс Метод Описание
/pay/payment post Запуск оплаты

Параметры:

Параметр Описание Обязательно
appid Идентификатор публичного аккаунта Да
mch_id Идентификатор, присвоенный платёжной системой WeChat Да
trade_type Тип транзакции: NATIVE, JSAPI, APP Нет (по умолчанию NATIVE)
order_id ID заказа Да

Пример запроса:

axios.post("/pay/payment",{
    appid: "wxed58e834201d0894",
    mch_id: 1568650321,
    order_id: 20201231103338122jnvk4na61h
})

Ответ в случае успешного выполнения запроса:

{
    "status": 200,
    "state": true,
    "msg": "OK",
    "prepay_id": "wx301847582783578da0cb5e1a6f24890000",
    "trade_type": "NATIVE",
    "code_url": "weixin://wxpay/bizpayurl?pr=hPUTMw4zz"
}

С помощью code_url можно создать QR-код для оплаты.

6.2. Проверка статуса платежа по заказу

  • Описание: Подходит для прямых платежей (режим прямого подключения).

  • URL запроса: https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/{out_trade_no}

  • Метод: GET

  • Параметры:

    Параметр Переменная Тип [ограничение длины] Обязательный Описание
    Идентификатор прямого партнёра mchid string[1,32] Да Идентификатор, предоставленный платёжной системой WeChat.
    Номер заказа партнёра out_trade_no string[1,32] Да Внутренний номер заказа в системе партнёра.
  • Пример запроса:

    https://api.mch.weixin.qq.com/v3/pay/transactions/out-trade-no/1217752501201407033233368018?mchid=1230000109
  • Ответ:

    Параметр Переменная Тип [ограничение длины] Обязательный Описание
    Идентификатор приложения appid string[1,32] Да Идентификатор публичного аккаунта или мобильного приложения.
    Идентификатор прямого партнёра mchid string[1,32] Да Идентификатор, предоставленный платёжной системой WeChat.
    Номер заказа партнёра out_trade_no string[6,32] Да Внутренний номер заказа в системе партнёра, должен быть уникальным в пределах одного идентификатора партнёра и состоять только из цифр, букв, символов _-*
    Идентификатор платежа WeChat transaction_id string[1,32] Нет Идентификатор платежа, созданный платёжной системой WeChat.
    Тип транзакции trade_type string[1,16] Нет Тип транзакции, возможные значения: JSAPI — оплата через публичный аккаунт, NATIVE — оплата с помощью сканирования QR-кода, APP — оплата через мобильное приложение, MICROPAY — оплата с использованием платёжного кода, MWEB — оплата в мобильном приложении, FACEPAY — оплата лицом.
    Статус транзакции trade_state string[1,32] Да Статус транзакции, возможные значения: SUCCESS — успешная оплата, REFUND — возврат средств, NOTPAY — неоплаченная транзакция, CLOSED — закрытая транзакция, REVOKED — отменённая транзакция (только для платежей с использованием платёжных кодов), USERPAYING — пользователь производит оплату (только для платежей с использованием платёжных кодов).
    Описание статуса транзакции trade_state_desc string[1,256] Да Описание состояния транзакции.
    Банк bank_type string[1,16] Нет Обозначение банка в виде строки.
    Дополнительные данные attach string[1,128] Нет Дополнительные данные, которые передаются без изменений в запросах API и уведомлениях об оплате и могут использоваться как настраиваемые параметры.
    Время завершения оплаты success_time string[1,64] Нет Время завершения платежа в формате YYYY-MM-DDTHH:mm:ss+TIMEZONE, где YYYY-MM-DD обозначает год, месяц и день, T указывает на начало элемента time, HH:mm:ss обозначает время, а TIMEZONE — часовой пояс (+08:00 обозначает смещение на 8 часов вперёд относительно UTC, то есть соответствует часовому поясу Пекина).

| :-- | :-- | :-- | :--: | :---------------------------------------------------------------------------------------------- | | +Сцена информации | scene_info | объект | Нет | Идентификатор устройства | | | +Информация о скидках | promotion_detail | массив | Нет | Информация о скидках, возвращается в этом поле при использовании скидок. |

Пример ответа

{
    "transaction_id": "1217752501201407033233368018",
    "amount": {
        "payer_total": 100,
        "total": 100,
        "currency": "CNY",
        "payer_currency": "CNY"
    },
    "mchid": "1230000109",
    "trade_state": "SUCCESS",
    "bank_type": "CMC",
    "promotion_detail": [{
        "amount": 100,
        "wechatpay_contribute": 0,
        "coupon_id": "109519",
        "scope": "GLOBALSINGLE",
        "merchant_contribute": 0,
        "name": "Скидка на один товар - 6",
        "other_contribute": 0,
        "currency": "CNY",
        "type": "CASHNOCASH",
        "stock_id": "931386",
        "goods_detail": [{
            "goods_remark": "Замечания к товару",
            "quantity": 1,
            "discount_amount": 1,
            "goods_id": "M1006",
            "unit_price": 100
        }, {
            "goods_remark": "Замечания к товару",
            "quantity": 1,
            "discount_amount": 1,
            "goods_id": "M1006",
            "unit_price": 100
        }]
    }, {
        "amount": 100,
        "wechatpay_contribute": 0,
        "coupon_id": "109519",
        "scope": "GLOBALSINGLE",
        "merchant_contribute": 0,
        "name": "Скидка на один товар - 6",
        "other_contribute": 0,
        "currency": "CNY",
        "type": "CASHNOCASH",
        "stock_id": "931386",
        "goods_detail": [{
            "goods_remark": "Замечания к товару",
            "quantity": 1,
            "discount_amount": 1,
            "goods_id": "M1006",
            "unit_price": 100
        }, {
            "goods_remark": "Замечания к товару",
            "quantity": 1,
            "discount_amount": 1,
            "goods_id": "M1006",
            "unit_price": 100
        }]
    }],
    "success_time": "2018-06-08T10:34:56+08:00",
    "payer": {
        "openid": "oUpF8uMuAJO_M2pxb1Q9zNjWeS6o"
    },
    "out_trade_no": "1217752501201407033233368018",
    "appid": "wxd678efh567hg6787",
    "trade_state_desc": "Платёж не удался, пожалуйста, повторите попытку оплаты",
    "trade_type": "MICROPAY",
    "attach": "Пользовательские данные",
    "scene_info": {
        "device_id": "013467007045764"
    }
}

Таблица кодов ошибок (общепринятые коды ошибок)

Статус Код ошибки Описание Решение
202 USERPAYING Платёж в процессе, требуется ввести пароль Подождите 5 секунд, затем вызовите API для запроса результатов сканирования заказа, чтобы определить текущее состояние заказа и принять решение о дальнейших действиях
403 TRADE_ERROR Ошибка транзакции Из-за бизнес-причин транзакция не удалась, проверьте подробную информацию в ответе API
500 SYSTEMERROR Системная ошибка Система выдала исключение, используйте те же параметры для повторного вызова
401 SIGN_ERROR Ошибка подписи Проверьте, соответствуют ли параметры и метод требованиям алгоритма подписи
403 RULELIMIT Ограничение бизнес-правил Частота запросов ограничена бизнес-правилами, проверьте подробную информацию об ответе API
400 PARAM_ERROR Ошибки параметров Проверьте запрос на основе подробной информации в ответе
403 OUT_TRADE_NO_USED Повторное использование номера заказа Убедитесь, что номер заказа не был отправлен повторно
403 ORDERNOTEXIST Заказ не существует Проверьте, была ли инициирована транзакция для этого заказа
400 ORDER_CLOSED Заказ закрыт Текущий заказ закрыт, создайте новый заказ
500 OPENID_MISMATCH Несоответствие openid и appid Убедитесь, что openid и appid совпадают
403 NOTENOUGH Недостаточный баланс
---------- ---------------- -----------------
403 NOAUTH У продавца нет прав доступа. Продавцу необходимо подать запрос на получение соответствующих прав для этого интерфейса.
400 MCH_NOT_EXISTS Номер продавца не существует. Проверьте правильность номера продавца.
500 INVALID_TRANSACTIONID Неверный номер заказа. Проверьте, правильно ли указан номер заказа в системе оплаты через WeChat.
400 INVALID_REQUEST Недействительный запрос. Пожалуйста, проверьте информацию, предоставленную в ответном сообщении интерфейса.
429 FREQUENCY_LIMITED Превышена частота запросов. Необходимо уменьшить частоту запросов к интерфейсу.
500 BANKERROR Ошибка банковской системы. Произошла ошибка в банковской системе. Используйте те же параметры и попробуйте вызвать интерфейс ещё раз.
400 APPID_MCHID_NOT_MATCH Идентификаторы appid и mch_id не совпадают. Убедитесь, что идентификаторы appid и mch_id совпадают.
403 ACCOUNTERROR Ошибка учётной записи. Учётная запись пользователя имеет ошибку. Дальнейшие действия не требуются.

Комментарии ( 0 )

Вы можете оставить комментарий после Вход в систему

Введение

1. Права доступа к меню. 2. Проверка прав ролей. 3. Проверка прав маршрутов. 4. Оплата через WeChat. 5. Добавление товаров, оформление заказа с оплатой через WeChat. 6. Вход с мобильного устройства с проверкой подлинности. 7. Вход в мини-приложение WeChat с мобильного устройства. 8. Быстрый вход в приложение. Развернуть Свернуть
JavaScript и 5 других языков
Отмена

Обновления (1)

все

Участники

все

Недавние действия

Загрузить больше
Больше нет результатов для загрузки
1
https://api.gitlife.ru/oschina-mirror/d718781500-student_product_manager_system.git
git@api.gitlife.ru:oschina-mirror/d718781500-student_product_manager_system.git
oschina-mirror
d718781500-student_product_manager_system
d718781500-student_product_manager_system
next