├── static
├── .gitkeep
└── img
│ ├── preload.png
│ ├── recomend.png
│ ├── success.png
│ ├── open_in_weixin.png
│ └── share_in_weixin.png
├── test
├── unit
│ ├── setup.js
│ ├── .eslintrc
│ ├── specs
│ │ └── HelloWorld.spec.js
│ └── jest.conf.js
└── e2e
│ ├── specs
│ └── test.js
│ ├── custom-assertions
│ └── elementCount.js
│ ├── nightwatch.conf.js
│ └── runner.js
├── .eslintignore
├── config
├── prod.env.js
├── test.env.js
├── dev.env.js
└── index.js
├── screenshots
├── fav.png
├── post.png
├── index.png
├── articlelist.png
├── circledetail.png
├── circlelist.png
├── storedetail.png
├── storeindex.png
├── articledetail.png
├── articledetail2.png
├── articledetail3.png
├── circledetail2.png
├── circledetail3.png
├── collectionlist.png
├── collectiondetail.png
├── collectiondetail11.png
└── collectiondetail12.png
├── src
├── assets
│ └── gotop.png
├── fonts
│ ├── MaterialIcons-Regular.eot
│ ├── MaterialIcons-Regular.ttf
│ ├── Framework7Icons-Regular.eot
│ ├── Framework7Icons-Regular.ttf
│ ├── Framework7Icons-Regular.woff
│ ├── MaterialIcons-Regular.woff
│ ├── MaterialIcons-Regular.woff2
│ ├── fontawesome-webfont93e3.eot
│ ├── fontawesome-webfont93e3.ttf
│ ├── fontawesome-webfont93e3.woff
│ ├── fontawesome-webfontd41d.eot
│ ├── Framework7Icons-Regular.woff2
│ ├── fontawesome-webfont93e3.woff2
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.ttf
│ ├── glyphicons-halflings-regular.woff
│ ├── glyphicons-halflings-regular.woff2
│ └── glyphicons-halflings-regulard41d.eot
├── store
│ ├── mutation-types.js
│ ├── index.js
│ ├── getters.js
│ ├── actions.js
│ └── mutations.js
├── css
│ ├── webuploader
│ │ └── webuploader.css
│ ├── icons.css
│ ├── article.css
│ └── webuploader-demo.min.css
├── .project
├── hiapp-pages
│ ├── feedback.vue
│ ├── home.vue
│ ├── language.vue
│ ├── publisher.vue
│ ├── comment.vue
│ ├── profile.vue
│ ├── contacts.vue
│ ├── about.vue
│ ├── settings.vue
│ ├── message.vue
│ ├── card.vue
│ └── post.vue
├── js
│ ├── config.js
│ ├── myAmap.js
│ ├── wxShare.js
│ ├── plugin
│ │ └── jquery.lazyload.min.js
│ └── f7-base.js
├── components
│ ├── remote-js.vue
│ ├── editor.vue
│ └── card.vue
├── pages
│ ├── home.vue
│ ├── not-found.vue
│ ├── my
│ │ ├── follow-member.vue
│ │ ├── fav-collection.vue
│ │ ├── fav-store.vue
│ │ ├── fav-goods.vue
│ │ ├── fav-article.vue
│ │ ├── follow-circle.vue
│ │ ├── circletheme.vue
│ │ └── fav-circletheme.vue
│ ├── form.vue
│ ├── circle-list.vue
│ ├── collection-list.vue
│ ├── article-list.vue
│ ├── store-list.vue
│ └── store-index.vue
├── main.js
├── App.vue
└── router
│ └── index.js
├── .editorconfig
├── .gitignore
├── .postcssrc.js
├── .babelrc
├── .project
├── index.html
├── package.json
└── README.md
/static/.gitkeep:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/test/unit/setup.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | Vue.config.productionTip = false
4 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | /build/
2 | /src/
3 | /config/
4 | /dist/
5 | /*.js
6 | /test/unit/coverage/
7 |
--------------------------------------------------------------------------------
/config/prod.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | module.exports = {
3 | NODE_ENV: '"production"'
4 | }
5 |
--------------------------------------------------------------------------------
/screenshots/fav.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/fav.png
--------------------------------------------------------------------------------
/screenshots/post.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/post.png
--------------------------------------------------------------------------------
/src/assets/gotop.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/assets/gotop.png
--------------------------------------------------------------------------------
/screenshots/index.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/index.png
--------------------------------------------------------------------------------
/static/img/preload.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/static/img/preload.png
--------------------------------------------------------------------------------
/static/img/recomend.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/static/img/recomend.png
--------------------------------------------------------------------------------
/static/img/success.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/static/img/success.png
--------------------------------------------------------------------------------
/test/unit/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "env": {
3 | "jest": true
4 | },
5 | "globals": {
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/screenshots/articlelist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/articlelist.png
--------------------------------------------------------------------------------
/screenshots/circledetail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/circledetail.png
--------------------------------------------------------------------------------
/screenshots/circlelist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/circlelist.png
--------------------------------------------------------------------------------
/screenshots/storedetail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/storedetail.png
--------------------------------------------------------------------------------
/screenshots/storeindex.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/storeindex.png
--------------------------------------------------------------------------------
/screenshots/articledetail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/articledetail.png
--------------------------------------------------------------------------------
/screenshots/articledetail2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/articledetail2.png
--------------------------------------------------------------------------------
/screenshots/articledetail3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/articledetail3.png
--------------------------------------------------------------------------------
/screenshots/circledetail2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/circledetail2.png
--------------------------------------------------------------------------------
/screenshots/circledetail3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/circledetail3.png
--------------------------------------------------------------------------------
/screenshots/collectionlist.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/collectionlist.png
--------------------------------------------------------------------------------
/static/img/open_in_weixin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/static/img/open_in_weixin.png
--------------------------------------------------------------------------------
/static/img/share_in_weixin.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/static/img/share_in_weixin.png
--------------------------------------------------------------------------------
/screenshots/collectiondetail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/collectiondetail.png
--------------------------------------------------------------------------------
/screenshots/collectiondetail11.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/collectiondetail11.png
--------------------------------------------------------------------------------
/screenshots/collectiondetail12.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/screenshots/collectiondetail12.png
--------------------------------------------------------------------------------
/src/fonts/MaterialIcons-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/MaterialIcons-Regular.eot
--------------------------------------------------------------------------------
/src/fonts/MaterialIcons-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/MaterialIcons-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/Framework7Icons-Regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/Framework7Icons-Regular.eot
--------------------------------------------------------------------------------
/src/fonts/Framework7Icons-Regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/Framework7Icons-Regular.ttf
--------------------------------------------------------------------------------
/src/fonts/Framework7Icons-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/Framework7Icons-Regular.woff
--------------------------------------------------------------------------------
/src/fonts/MaterialIcons-Regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/MaterialIcons-Regular.woff
--------------------------------------------------------------------------------
/src/fonts/MaterialIcons-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/MaterialIcons-Regular.woff2
--------------------------------------------------------------------------------
/src/fonts/fontawesome-webfont93e3.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/fontawesome-webfont93e3.eot
--------------------------------------------------------------------------------
/src/fonts/fontawesome-webfont93e3.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/fontawesome-webfont93e3.ttf
--------------------------------------------------------------------------------
/src/fonts/fontawesome-webfont93e3.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/fontawesome-webfont93e3.woff
--------------------------------------------------------------------------------
/src/fonts/fontawesome-webfontd41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/fontawesome-webfontd41d.eot
--------------------------------------------------------------------------------
/src/fonts/Framework7Icons-Regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/Framework7Icons-Regular.woff2
--------------------------------------------------------------------------------
/src/fonts/fontawesome-webfont93e3.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/fontawesome-webfont93e3.woff2
--------------------------------------------------------------------------------
/src/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/src/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/src/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/src/fonts/glyphicons-halflings-regular.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/glyphicons-halflings-regular.woff2
--------------------------------------------------------------------------------
/src/fonts/glyphicons-halflings-regulard41d.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/evangui/vue-f7-circle/HEAD/src/fonts/glyphicons-halflings-regulard41d.eot
--------------------------------------------------------------------------------
/src/store/mutation-types.js:
--------------------------------------------------------------------------------
1 | export const INIT_CONTACTS = 'INIT_CONTACTS'
2 | export const INIT_TIMETIME = 'INIT_TIMETIME'
3 | export const UPDATE_TIMETIME = 'UPDATE_TIMETIME'
4 |
--------------------------------------------------------------------------------
/config/test.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const devEnv = require('./dev.env')
4 |
5 | module.exports = merge(devEnv, {
6 | NODE_ENV: '"testing"'
7 | })
8 |
--------------------------------------------------------------------------------
/config/dev.env.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | const merge = require('webpack-merge')
3 | const prodEnv = require('./prod.env')
4 |
5 | module.exports = merge(prodEnv, {
6 | NODE_ENV: '"development"'
7 | })
8 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | charset = utf-8
5 | indent_style = space
6 | indent_size = 2
7 | end_of_line = lf
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules/
3 | /dist/
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | /test/unit/coverage/
8 | /test/e2e/reports/
9 | selenium-debug.log
10 |
11 | # Editor directories and files
12 | .idea
13 | .vscode
14 | *.suo
15 | *.ntvs*
16 | *.njsproj
17 | *.sln
18 |
--------------------------------------------------------------------------------
/.postcssrc.js:
--------------------------------------------------------------------------------
1 | // https://github.com/michael-ciniawsky/postcss-load-config
2 |
3 | module.exports = {
4 | "plugins": {
5 | "postcss-import": {},
6 | "postcss-url": {},
7 | // to edit target browsers: use "browserslist" field in package.json
8 | "autoprefixer": {}
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/test/unit/specs/HelloWorld.spec.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import HelloWorld from '@/components/HelloWorld'
3 |
4 | describe('HelloWorld.vue', () => {
5 | it('should render correct contents', () => {
6 | const Constructor = Vue.extend(HelloWorld)
7 | const vm = new Constructor().$mount()
8 | expect(vm.$el.querySelector('.hello h1').textContent)
9 | .toEqual('Welcome to Your Vue.js App')
10 | })
11 | })
12 |
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["env", {
4 | "modules": false,
5 | "targets": {
6 | "browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
7 | }
8 | }],
9 | "stage-2"
10 | ],
11 | "plugins": ["transform-vue-jsx", "transform-runtime"],
12 | "env": {
13 | "test": {
14 | "presets": ["env", "stage-2"],
15 | "plugins": ["transform-vue-jsx", "transform-es2015-modules-commonjs", "dynamic-import-node"]
16 | }
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/test/e2e/specs/test.js:
--------------------------------------------------------------------------------
1 | // For authoring Nightwatch tests, see
2 | // http://nightwatchjs.org/guide#usage
3 |
4 | module.exports = {
5 | 'default e2e tests': function (browser) {
6 | // automatically uses dev Server port from /config.index.js
7 | // default: http://localhost:8080
8 | // see nightwatch.conf.js
9 | const devServer = browser.globals.devServerURL
10 |
11 | browser
12 | .url(devServer)
13 | .waitForElementVisible('#app', 5000)
14 | .assert.elementPresent('.hello')
15 | .assert.containsText('h1', 'Welcome to Your Vue.js App')
16 | .assert.elementCount('img', 1)
17 | .end()
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/src/css/webuploader/webuploader.css:
--------------------------------------------------------------------------------
1 | .webuploader-container {
2 | position: relative;
3 | }
4 | .webuploader-element-invisible {
5 | position: absolute !important;
6 | clip: rect(1px 1px 1px 1px); /* IE6, IE7 */
7 | clip: rect(1px,1px,1px,1px);
8 | }
9 | .webuploader-pick {
10 | position: relative;
11 | display: inline-block;
12 | cursor: pointer;
13 | background: #00b7ee;
14 | padding: 10px 15px;
15 | color: #fff;
16 | text-align: center;
17 | border-radius: 3px;
18 | overflow: hidden;
19 | }
20 | .webuploader-pick-hover {
21 | background: #00a2d4;
22 | }
23 |
24 | .webuploader-pick-disable {
25 | opacity: 0.6;
26 | pointer-events:none;
27 | }
28 |
29 |
--------------------------------------------------------------------------------
/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | hnp-vue
4 |
5 |
6 |
7 |
8 |
9 | com.aptana.ide.core.unifiedBuilder
10 |
11 |
12 |
13 |
14 |
15 | com.aptana.projects.webnature
16 |
17 |
18 |
19 | 1522493752490
20 |
21 | 26
22 |
23 | org.eclipse.ui.ide.multiFilter
24 | 1.0-name-matches-false-false-node_modules
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/src/.project:
--------------------------------------------------------------------------------
1 |
2 |
3 | vue-myproject
4 |
5 |
6 |
7 |
8 |
9 | com.aptana.ide.core.unifiedBuilder
10 |
11 |
12 |
13 |
14 |
15 | com.aptana.projects.webnature
16 |
17 |
18 |
19 | 0
20 |
21 | 26
22 |
23 | org.eclipse.ui.ide.multiFilter
24 | 1.0-name-matches-false-false-node_modules
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | 杏运树
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/test/unit/jest.conf.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 |
3 | module.exports = {
4 | rootDir: path.resolve(__dirname, '../../'),
5 | moduleFileExtensions: [
6 | 'js',
7 | 'json',
8 | 'vue'
9 | ],
10 | moduleNameMapper: {
11 | '^@/(.*)$': '/src/$1'
12 | },
13 | transform: {
14 | '^.+\\.js$': '/node_modules/babel-jest',
15 | '.*\\.(vue)$': '/node_modules/vue-jest'
16 | },
17 | testPathIgnorePatterns: [
18 | '/test/e2e'
19 | ],
20 | snapshotSerializers: ['/node_modules/jest-serializer-vue'],
21 | setupFiles: ['/test/unit/setup'],
22 | mapCoverage: true,
23 | coverageDirectory: '/test/unit/coverage',
24 | collectCoverageFrom: [
25 | 'src/**/*.{js,vue}',
26 | '!src/main.js',
27 | '!src/router/index.js',
28 | '!**/node_modules/**'
29 | ]
30 | }
31 |
--------------------------------------------------------------------------------
/src/hiapp-pages/feedback.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Vuex from 'vuex'
3 | import * as actions from './actions'
4 | import mutations from './mutations'
5 | import getters from './getters'
6 |
7 | import vuexAlong from 'vuex-along';
8 |
9 | Vue.use(Vuex)
10 | //vuexAlong.watch(['localNum'],true);
11 | //vuexAlong.watchSession(['sessionNum'],true);
12 | vuexAlong.onlySession(true);
13 |
14 |
15 | const state = {
16 | position: {},
17 | mutArticlesState: {a:1},
18 | mutArticleRepliesState: {a:1},
19 |
20 | mutCollectionsState: {a:1},
21 | mutCirclesState: {a:1},
22 | mutThemesState: {a:1},
23 | mutThemeRepliesState: {a:1},
24 | mutStoresState: {},
25 | mutGoodsState: {},
26 | }
27 |
28 | export default new Vuex.Store({
29 | // strict: process.env.NODE_ENV !== 'production',
30 | state,
31 | getters,
32 | actions,
33 | mutations,
34 | plugins: [vuexAlong]
35 | })
--------------------------------------------------------------------------------
/src/js/config.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 环境相关配置文件
3 | */
4 | let serverIndex;
5 | switch (document.location.host){
6 | case 'm2.cattlepie.com':
7 | serverIndex = '2';
8 | break;
9 | case 'm1.cattlepie.com':
10 | serverIndex = '1';
11 | break;
12 | case 'm.cattlepie.com':
13 | case 'm.cattlepie.me':
14 | serverIndex = '';
15 | break;
16 | default:
17 | serverIndex = '2';
18 | break;
19 | }
20 |
21 | //serverIndex = '';
22 | var domainSuffix = '.com'; //.me or .com
23 |
24 | var config = {
25 | domainSuffix : domainSuffix,
26 | apiUrl: '//apidev' + serverIndex + '.cattlepie' + domainSuffix + '/',
27 | siteUrl: '//' + document.location.host + '/',
28 | userSiteUrl: '//m' + serverIndex + '.cattlepie' + domainSuffix + '/',
29 | shopSiteUrl: '//m' + serverIndex + '.cattlepie' + domainSuffix + '/',
30 | imgServer: 'http://img0.cattlepie.com/',
31 | }
32 |
33 | export default config;
--------------------------------------------------------------------------------
/src/components/remote-js.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/src/hiapp-pages/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
10 |
11 |
--------------------------------------------------------------------------------
/test/e2e/custom-assertions/elementCount.js:
--------------------------------------------------------------------------------
1 | // A custom Nightwatch assertion.
2 | // The assertion name is the filename.
3 | // Example usage:
4 | //
5 | // browser.assert.elementCount(selector, count)
6 | //
7 | // For more information on custom assertions see:
8 | // http://nightwatchjs.org/guide#writing-custom-assertions
9 |
10 | exports.assertion = function (selector, count) {
11 | this.message = 'Testing if element <' + selector + '> has count: ' + count
12 | this.expected = count
13 | this.pass = function (val) {
14 | return val === this.expected
15 | }
16 | this.value = function (res) {
17 | return res.value
18 | }
19 | this.command = function (cb) {
20 | var self = this
21 | return this.api.execute(function (selector) {
22 | return document.querySelectorAll(selector).length
23 | }, [selector], function (res) {
24 | cb.call(self, res)
25 | })
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/src/pages/home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |

6 |
杏运树
7 |
8 |
11 |
12 |
13 |
14 |
15 |
16 |
19 |
20 |
--------------------------------------------------------------------------------
/src/hiapp-pages/language.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/hiapp-pages/publisher.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/src/hiapp-pages/comment.vue:
--------------------------------------------------------------------------------
1 |
2 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/test/e2e/nightwatch.conf.js:
--------------------------------------------------------------------------------
1 | require('babel-register')
2 | var config = require('../../config')
3 |
4 | // http://nightwatchjs.org/gettingstarted#settings-file
5 | module.exports = {
6 | src_folders: ['test/e2e/specs'],
7 | output_folder: 'test/e2e/reports',
8 | custom_assertions_path: ['test/e2e/custom-assertions'],
9 |
10 | selenium: {
11 | start_process: true,
12 | server_path: require('selenium-server').path,
13 | host: '127.0.0.1',
14 | port: 4444,
15 | cli_args: {
16 | 'webdriver.chrome.driver': require('chromedriver').path
17 | }
18 | },
19 |
20 | test_settings: {
21 | default: {
22 | selenium_port: 4444,
23 | selenium_host: 'localhost',
24 | silent: true,
25 | globals: {
26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port)
27 | }
28 | },
29 |
30 | chrome: {
31 | desiredCapabilities: {
32 | browserName: 'chrome',
33 | javascriptEnabled: true,
34 | acceptSslCerts: true
35 | }
36 | },
37 |
38 | firefox: {
39 | desiredCapabilities: {
40 | browserName: 'firefox',
41 | javascriptEnabled: true,
42 | acceptSslCerts: true
43 | }
44 | }
45 | }
46 | }
47 |
--------------------------------------------------------------------------------
/src/hiapp-pages/profile.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
34 |
35 |
--------------------------------------------------------------------------------
/src/components/editor.vue:
--------------------------------------------------------------------------------
1 |
2 |
17 |
18 |
19 |
21 |
22 |
--------------------------------------------------------------------------------
/src/hiapp-pages/contacts.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
13 |
14 |
15 |
16 |
17 |
18 |
39 |
40 |
--------------------------------------------------------------------------------
/test/e2e/runner.js:
--------------------------------------------------------------------------------
1 | // 1. start the dev server using production config
2 | process.env.NODE_ENV = 'testing'
3 |
4 | const webpack = require('webpack')
5 | const DevServer = require('webpack-dev-server')
6 |
7 | const webpackConfig = require('../../build/webpack.prod.conf')
8 | const devConfigPromise = require('../../build/webpack.dev.conf')
9 |
10 | let server
11 |
12 | devConfigPromise.then(devConfig => {
13 | const devServerOptions = devConfig.devServer
14 | const compiler = webpack(webpackConfig)
15 | server = new DevServer(compiler, devServerOptions)
16 | const port = devServerOptions.port
17 | const host = devServerOptions.host
18 | return server.listen(port, host)
19 | })
20 | .then(() => {
21 | // 2. run the nightwatch test suite against it
22 | // to run in additional browsers:
23 | // 1. add an entry in test/e2e/nightwatch.conf.js under "test_settings"
24 | // 2. add it to the --env flag below
25 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox`
26 | // For more information on Nightwatch's config file, see
27 | // http://nightwatchjs.org/guide#settings-file
28 | let opts = process.argv.slice(2)
29 | if (opts.indexOf('--config') === -1) {
30 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js'])
31 | }
32 | if (opts.indexOf('--env') === -1) {
33 | opts = opts.concat(['--env', 'chrome'])
34 | }
35 |
36 | const spawn = require('cross-spawn')
37 | const runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' })
38 |
39 | runner.on('exit', function (code) {
40 | server.close()
41 | process.exit(code)
42 | })
43 |
44 | runner.on('error', function (err) {
45 | server.close()
46 | throw err
47 | })
48 | })
49 |
--------------------------------------------------------------------------------
/src/hiapp-pages/about.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |

7 |
8 | HiApp
9 |
10 |
11 | GitHub: BelinChung/HiApp
12 | Email: BelinChung@gmail.com
13 | Twitter: @BelinChung
14 |
15 |
16 | Copyright © 2017 BelinChung.
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/src/pages/not-found.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |

6 |
7 |
8 |
9 |
亲,你可能迷路了!
10 |
11 |
问题反馈
12 |
13 |
14 |
15 |
16 |
38 |
39 |
40 |
41 |
42 |
45 |
46 |
--------------------------------------------------------------------------------
/src/store/getters.js:
--------------------------------------------------------------------------------
1 | export default {
2 | // checkoutStatus: state => state.checkoutStatus,
3 |
4 | getMutArticle: (state) => (id, init=1) => {
5 | return state.mutArticlesState['k' + id] || (init ? {
6 | article_id : 0,
7 | article_like_count : 0,
8 | article_click: 0,
9 | article_up: 0,
10 | article_comment_count: 0,
11 | liked: 0,
12 | uped:0,
13 | } : undefined);
14 |
15 | // return state.added.map(item => {
16 | // const product = state.products.all.find(product => product.id === id)
17 | // return {
18 | // title: product.title,
19 | // price: product.price,
20 | // quantity: item.quantity
21 | // }
22 | // })
23 | },
24 |
25 | getMutArticleReply: (state) => (id, init=1) => {
26 | return state.mutArticleRepliesState['k' + id] || (init ? {
27 | reply_up : 0,
28 | uped: 0,
29 | } : undefined);
30 |
31 | },
32 |
33 | getMutThemeReply: (state) => (id, init=1) => {
34 | return state.mutThemeRepliesState['k' + id] || (init ? {
35 | reply_up : 0,
36 | uped: 0,
37 | } : undefined);
38 |
39 | },
40 |
41 | getMutCollection: (state) => (id, init=1) => {
42 | return state.mutCollectionsState['k' + id] || (init ? {
43 | cl_like_count : 0,
44 | liked: 0,
45 | } : undefined);
46 | },
47 |
48 | getMutTheme: (state) => (id, init=1) => {
49 | return state.mutThemesState['k' + id] || (init ? {
50 | theme_like_count : 0,
51 | theme_up_count: 0,
52 | theme_commentcount: 0,
53 | liked: 0,
54 | uped: 0,
55 | } : undefined);
56 | },
57 |
58 | getMutCircle: (state) => (id, init=1) => {
59 | return state.mutCirclesState['k' + id] || (init ? {
60 | circle_thcount : 0,
61 | circle_mcount: 0,
62 | joined: 0,
63 | } : undefined);
64 |
65 | },
66 |
67 | getMutStore: (state) => (id, init=1) => {
68 | return state.mutStoresState['k' + id] || (init ? {
69 | // store_like_count : 0,
70 | liked: 0,
71 | } : undefined);
72 | },
73 |
74 | getMutGoods: (state) => (id, init=1) => {
75 | return state.mutGoodsState['k' + id] || (init ? {
76 | // store_like_count : 0,
77 | liked: 0,
78 | } : undefined);
79 | },
80 |
81 | }
--------------------------------------------------------------------------------
/src/css/icons.css:
--------------------------------------------------------------------------------
1 | /* Material Icons Font (for MD theme) */
2 | @font-face {
3 | font-family: 'Material Icons';
4 | font-style: normal;
5 | font-weight: 400;
6 | src: url(../fonts/MaterialIcons-Regular.eot); /* For IE6-8 */
7 | src: local('Material Icons'),
8 | local('MaterialIcons-Regular'),
9 | url(../fonts/MaterialIcons-Regular.woff2) format('woff2'),
10 | url(../fonts/MaterialIcons-Regular.woff) format('woff'),
11 | url(../fonts/MaterialIcons-Regular.ttf) format('truetype');
12 | }
13 |
14 | .material-icons {
15 | font-family: 'Material Icons';
16 | font-weight: normal;
17 | font-style: normal;
18 | font-size: 24px; /* Preferred icon size */
19 | display: inline-block;
20 | line-height: 1;
21 | text-transform: none;
22 | letter-spacing: normal;
23 | word-wrap: normal;
24 | white-space: nowrap;
25 | direction: ltr;
26 |
27 | /* Support for all WebKit browsers. */
28 | -webkit-font-smoothing: antialiased;
29 | /* Support for Safari and Chrome. */
30 | text-rendering: optimizeLegibility;
31 |
32 | /* Support for Firefox. */
33 | -moz-osx-font-smoothing: grayscale;
34 |
35 | /* Support for IE. */
36 | font-feature-settings: 'liga';
37 | }
38 |
39 | /* Framework7 Icons Font (for iOS theme) */
40 | @font-face {
41 | font-family: 'Framework7 Icons';
42 | font-style: normal;
43 | font-weight: 400;
44 | src: url("../fonts/Framework7Icons-Regular.eot");
45 | src: url("../fonts/Framework7Icons-Regular.woff2") format("woff2"),
46 | url("../fonts/Framework7Icons-Regular.woff") format("woff"),
47 | url("../fonts/Framework7Icons-Regular.ttf") format("truetype");
48 | }
49 |
50 | .f7-icons {
51 | font-family: 'Framework7 Icons';
52 | font-weight: normal;
53 | font-style: normal;
54 | font-size: 25px;
55 | line-height: 1;
56 | letter-spacing: normal;
57 | text-transform: none;
58 | display: inline-block;
59 | white-space: nowrap;
60 | word-wrap: normal;
61 | direction: ltr;
62 | -webkit-font-smoothing: antialiased;
63 | text-rendering: optimizeLegibility;
64 | -moz-osx-font-smoothing: grayscale;
65 | -webkit-font-feature-settings: "liga";
66 | -moz-font-feature-settings: "liga=1";
67 | -moz-font-feature-settings: "liga";
68 | font-feature-settings: "liga";
69 | text-align: center;
70 | }
71 |
--------------------------------------------------------------------------------
/src/main.js:
--------------------------------------------------------------------------------
1 | // Ponyfill
2 | //import 'es6-object-assign/auto'
3 | //import 'es6-promise/auto'
4 | import 'babel-polyfill';// 或者require('babel-polyfill');
5 |
6 | // Import F7 Styles
7 | import Framework7Styles from 'framework7/dist/css/framework7.ios.min.css';
8 |
9 | // Import Icons and App Custom Styles
10 | import './css/font-awesome.min.css';
11 | import IconsStyles from './css/icons.css';
12 | //import AliIconsStyles from 'at.alicdn.com/t/font_551867_u8ixrzn4edji3sor.css';
13 | import AppStyles from './css/app.css';
14 |
15 | import Vue from 'vue'
16 | import App from './App'
17 | import router from './router'
18 |
19 | // Import Vuex store
20 | import store from './store'
21 |
22 | Vue.config.productionTip = false
23 |
24 | //vue-lazyload
25 | import VueLazyload from 'vue-lazyload';
26 | Vue.use(VueLazyload, {
27 | preLoad: 1.3,
28 | error: 'static/img/preload.png',
29 | loading: 'static/img/preload.png',
30 | attempt: 2
31 | });
32 |
33 | //引入vue基础框架
34 | import base from './js/base.js';
35 | import config from './js/config.js';
36 | import wap from './js/wap.js';
37 | Vue.use(base, config, wap);
38 |
39 | //引入f7基础框架
40 | //import Framework7 from 'framework7/dist/framework7.esm.bundle.js';
41 | import Framework7 from 'framework7';
42 | import Swiper from 'framework7/dist/components/swiper/swiper.js';
43 | import Popup from 'framework7/dist/components/popup/popup.js';
44 | import Popover from 'framework7/dist/components/popover/popover.js';
45 | import Preloader from 'framework7/dist/components/preloader/preloader.js';
46 | import PullToRefresh from 'framework7/dist/components/pull-to-refresh/pull-to-refresh.js';
47 | import Toast from 'framework7/dist/components/toast/toast.js';
48 | import PhotoBrowser from 'framework7/dist/components/photo-browser/photo-browser.js';
49 | import Dialog from 'framework7/dist/components/dialog/dialog.js';
50 | import Sheet from 'framework7/dist/components/sheet/sheet.js';
51 | import InfiniteScroll from 'framework7/dist/components/infinite-scroll/infinite-scroll.js';
52 |
53 | Framework7.use([Swiper,Popup,Popover,Preloader,PullToRefresh,Toast,PhotoBrowser,Dialog,Sheet,InfiniteScroll]);
54 |
55 | import F7Base from './js/f7-base.js'
56 | Vue.use(F7Base, Framework7);
57 |
58 |
59 | var _hmt = window._hmt || []
60 |
61 | /* eslint-disable no-new */
62 | new Vue({
63 | el: '#app',
64 | store,
65 | router,
66 | components: { App },
67 | template: ''
68 | })
69 |
--------------------------------------------------------------------------------
/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
42 |
43 |
--------------------------------------------------------------------------------
/src/hiapp-pages/settings.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
{{userInfo.nickName}}
7 |
8 | {{$t('app.city')}}:
9 | {{userInfo.location}}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
63 |
64 |
--------------------------------------------------------------------------------
/config/index.js:
--------------------------------------------------------------------------------
1 | 'use strict'
2 | // Template version: 1.3.1
3 | // see http://vuejs-templates.github.io/webpack for documentation.
4 |
5 | const path = require('path')
6 |
7 | module.exports = {
8 | dev: {
9 |
10 | // Paths
11 | assetsSubDirectory: 'static',
12 | assetsPublicPath: '/',
13 | proxyTable: {},
14 |
15 | // Various Dev Server settings
16 | host: '192.168.0.108', // can be overwritten by process.env.HOST
17 | port: 9999, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
18 | autoOpenBrowser: false,
19 | errorOverlay: true,
20 | notifyOnErrors: true,
21 | poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
22 |
23 | // Use Eslint Loader?
24 | // If true, your code will be linted during bundling and
25 | // linting errors and warnings will be shown in the console.
26 | // useEslint: true,
27 | // If true, eslint errors and warnings will also be shown in the error overlay
28 | // in the browser.
29 | // showEslintErrorsInOverlay: false,
30 |
31 | /**
32 | * Source Maps
33 | */
34 |
35 | // https://webpack.js.org/configuration/devtool/#development
36 | devtool: 'cheap-module-eval-source-map',
37 |
38 | // If you have problems debugging vue-files in devtools,
39 | // set this to false - it *may* help
40 | // https://vue-loader.vuejs.org/en/options.html#cachebusting
41 | cacheBusting: true,
42 |
43 | cssSourceMap: true
44 | },
45 |
46 | build: {
47 | // Template for index.html
48 | index: path.resolve(__dirname, '../dist/index.html'),
49 |
50 | // Paths
51 | assetsRoot: path.resolve(__dirname, '../dist'),
52 | assetsSubDirectory: 'static',
53 | assetsPublicPath: '',
54 |
55 | /**
56 | * Source Maps
57 | */
58 |
59 | productionSourceMap: false,
60 | // https://webpack.js.org/configuration/devtool/#production
61 | devtool: '#source-map',
62 |
63 | // Gzip off by default as many popular static hosts such as
64 | // Surge or Netlify already gzip all static assets for you.
65 | // Before setting to `true`, make sure to:
66 | // npm install --save-dev compression-webpack-plugin
67 | productionGzip: false,
68 | productionGzipExtensions: ['js', 'css'],
69 |
70 | // Run the build command with an extra argument to
71 | // View the bundle analyzer report after build finishes:
72 | // `npm run build --report`
73 | // Set to `true` or `false` to always turn it on or off
74 | bundleAnalyzerReport: process.env.npm_config_report
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/src/js/myAmap.js:
--------------------------------------------------------------------------------
1 | //微信分享事件监听,常用功能封装
2 | var myAmap = function(opts) {
3 | var defaults = {
4 | title: '分享标题', //分享标题,不能为空
5 | desc: '', //分享描述,可以为空,(分享到朋友圈,不支持描述)
6 | link: '', //分享页面地址,不能为空
7 | imgUrl: '', //分享是封面图片,不能为空
8 | success: function() {}, //分享成功触发
9 | cancel: function() {} //分享取消触发,需要时可以调用
10 | }
11 | this.opts = arguments[0] ? opts : defaults;
12 | }
13 |
14 | myAmap.prototype = {
15 | plugnToolBar: function() {
16 | map.plugin(["AMap.ToolBar"], function() {
17 | map.addControl(new AMap.ToolBar());
18 | });
19 | if(location.href.indexOf('&guide=1') !== -1) {
20 | map.setStatus({
21 | scrollWheel: false
22 | })
23 | }
24 | },
25 |
26 | //逆地理编码
27 | //逆向地理编码
28 | // var x = localStorage.getItem('user_lng');
29 | // var y = localStorage.getItem('user_lat');
30 | // regeocoder([x, y]);
31 | regeocoder: function(lnglatXY) {
32 | AMap.plugin('AMap.Geocoder', function() {
33 | map.addControl(geocoder);
34 | })
35 | var geocoder = new AMap.Geocoder({
36 | radius: 1000,
37 | extensions: "all"
38 | });
39 |
40 | geocoder.getAddress(lnglatXY, function(status, result) {
41 | if(status === 'complete' && result.info === 'OK') {
42 | geocoder_CallBack(result);
43 | }
44 | });
45 |
46 | function geocoder_CallBack(data) {
47 | var address = data.regeocode.formattedAddress; //返回地址描述
48 | // alert(address);
49 | localStorage.setItem('locations', address);
50 | }
51 | },
52 |
53 | //请求地理位置定位
54 | reqLocation: function(onComplete, onError) {
55 | var onComplete = arguments[0] ? arguments[0] : onCompleteFunc;
56 | var onError = arguments[1] ? arguments[1] : onErrorFunc;
57 |
58 | var map, geolocation;
59 | //加载地图,调用浏览器定位服务
60 | map = new AMap.Map('container', {
61 | resizeEnable: true,
62 | });
63 |
64 | map.plugin('AMap.Geolocation', function() {
65 | geolocation = new AMap.Geolocation({
66 | enableHighAccuracy: true, //是否使用高精度定位,默认:true
67 | timeout: 1000, //超过10秒后停止定位,默认:无穷大
68 | zoom: 16,
69 | });
70 | map.addControl(geolocation);
71 | geolocation.getCurrentPosition();
72 | AMap.event.addListener(geolocation, 'complete', onComplete); //返回定位信息
73 | AMap.event.addListener(geolocation, 'error', onError); //返回定位出错信息
74 | });
75 |
76 | //解析定位结果
77 | function onCompleteFunc(data) {
78 | alert(data);
79 | console.log(data);
80 | var user_lng = data.position.getLng();
81 | var user_lat = data.position.getLat();
82 |
83 | var str = ['定位成功'];
84 | str.push('经度:' + user_lng);
85 | str.push('纬度:' + user_lat);
86 | localStorage.setItem('user_lng', user_lng);
87 | localStorage.setItem('user_lat', user_lat);
88 | }
89 |
90 | function onErrorFunc(data) {
91 | /*alert('定位失败');*/
92 | console.log(data)
93 | }
94 | },
95 | }
96 |
97 | export default myAmap;
98 |
--------------------------------------------------------------------------------
/src/js/wxShare.js:
--------------------------------------------------------------------------------
1 | //微信分享事件监听,常用功能封装
2 | (function() {
3 | var wxShare = function(opts) {
4 | var defaults = {
5 | title: '杏运树趣玩-一个好玩、好吃、好实惠的平台', //分享标题,不能为空
6 | desc: '让美食与运动成为一种健康习惯,让吃货用更佳的方式享悦生活!', //分享描述,可以为空,(分享到朋友圈,不支持描述)
7 | link: '', //分享页面地址,不能为空
8 | imgUrl: '', //分享是封面图片,不能为空
9 | success: function() {}, //分享成功触发
10 | cancel: function() {} //分享取消触发,需要时可以调用
11 | }
12 | this.opts = $.extend({}, defaults, opts);
13 | }
14 | wxShare.prototype = {
15 | //绑定微信朋友圈,发送朋友
16 | bindWX: function() {
17 | var _opts = this.opts;
18 | //监听,分享到朋友圈
19 | wx.onMenuShareTimeline({
20 | title: _opts.title,
21 | link: _opts.link,
22 | imgUrl: _opts.imgUrl,
23 | success: function() {
24 | if(_opts.success)
25 | _opts.success();
26 | },
27 | calcel: function() {
28 | if(_opts.cancel)
29 | _opts.cancel();
30 | }
31 | });
32 | //监听,分享给朋友 (type,dataurl基本可以放弃不使用)
33 | wx.onMenuShareAppMessage({
34 | title: _opts.title, // 分享标题
35 | desc: _opts.desc, // 分享描述
36 | link: _opts.link, // 分享链接
37 | imgUrl: _opts.imgUrl, // 分享图标
38 | success: function() {
39 | if(_opts.success)
40 | _opts.success();
41 | },
42 | cancel: function() {
43 | if(_opts.cancel)
44 | _opts.cancel();
45 | }
46 | });
47 | },
48 | //绑定QQ空间,QQ好友
49 | bindQQ: function() {
50 | var _opts = this.opts;
51 | //监听,分享到QQ空间
52 | wx.onMenuShareQZone({
53 | title: _opts.title, // 分享标题
54 | desc: _opts.desc, // 分享描述
55 | link: _opts.link, // 分享链接
56 | imgUrl: _opts.imgUrl, // 分享图标
57 | success: function() {
58 | if(_opts.success)
59 | _opts.success();
60 | },
61 | cancel: function() {
62 | if(_opts.cancel)
63 | _opts.cancel();
64 | }
65 | });
66 | //监听,分享到QQ
67 | wx.onMenuShareQQ({
68 | title: _opts.title, // 分享标题
69 | desc: _opts.desc, // 分享描述
70 | link: _opts.link, // 分享链接
71 | imgUrl: _opts.imgUrl, // 分享图标
72 | success: function() {
73 | if(_opts.success)
74 | _opts.success();
75 | },
76 | cancel: function() {
77 | if(_opts.cancel)
78 | _opts.cancel();
79 | }
80 | });
81 | },
82 | //绑定默认,不使用腾讯微博
83 | bind: function() {
84 | this.bindWX();
85 | this.bindQQ();
86 | },
87 | //绑定所有,包括腾讯微博
88 | bindAll: function() {
89 | this.bind();
90 | var _opts = this.opts;
91 | //监听,分享到腾讯微博 (基本可以放弃不使用)
92 | wx.onMenuShareWeibo({
93 | title: _opts.title, // 分享标题
94 | desc: _opts.desc, // 分享描述
95 | link: _opts.link, // 分享链接
96 | imgUrl: _opts.imgUrl, // 分享图标
97 | success: function() {
98 | if(_opts.success)
99 | _opts.success();
100 | },
101 | cancel: function() {
102 | if(_opts.cancel)
103 | _opts.cancel();
104 | }
105 | });
106 | }
107 | }
108 | window.wxShare = wxShare;
109 | })();
--------------------------------------------------------------------------------
/src/css/article.css:
--------------------------------------------------------------------------------
1 | article p {
2 | word-wrap: break-word;
3 | text-align: justify;
4 | margin: 0 0 20px;
5 | color: #505050;
6 | line-height: 1.7;
7 | padding: 0
8 | }
9 |
10 | article table {
11 | margin: 0 auto;
12 | font-size: 14px;
13 | text-align: center;
14 | border-spacing: 0;
15 | border-collapse: collapse;
16 | color: #303030
17 | }
18 |
19 | article table td {
20 | border: 1px solid #dadada;
21 | padding: 2px
22 | }
23 |
24 | article img {
25 | display: block;
26 | max-width: 100%;
27 | background: #efefef;
28 | border-radius: 0;
29 | margin: 8px auto
30 | }
31 |
32 | article h1,
33 | article h2,
34 | article h3,
35 | article h4 {
36 | position: relative;
37 | display: block;
38 | font-weight: 700;
39 | word-wrap: break-word;
40 | margin: 20px 0;
41 | padding-left: 9px;
42 | color: #333333;
43 | line-height: normal
44 | }
45 |
46 | article h1 {
47 | font-size: 1.1em;
48 | }
49 |
50 | article h2 {
51 | font-size: 1em;
52 | }
53 | article h3 {
54 | font-size: 1em;
55 | padding-left: 0;
56 | text-align: left;
57 | }
58 | article h4 {
59 | font-size: 1em;
60 | padding-left: 0;
61 | text-align: center;
62 | }
63 | article h5 {
64 | font-size: 0.9em;
65 | text-align: center;
66 | }
67 |
68 | article h1:before,
69 | article h2:before{
70 | content: '';
71 | position: absolute;
72 | width: 4px;
73 | height: 100%;
74 | top: 0;
75 | left: 0;
76 | background: #ff9500;
77 | border-radius: 20%;
78 | }
79 |
80 | article blockquote p {
81 | line-height: 1.6;
82 | margin: 0 0 20px;
83 | color: #999
84 | }
85 |
86 | article blockquote p:last-child {
87 | margin: 0
88 | }
89 |
90 | article blockquote p br:only-child {
91 | display: none
92 | }
93 |
94 | article pre,
95 | article code {
96 | font-size: 12px;
97 | line-height: 1.5em;
98 | background: #eee;
99 | padding: 10px
100 | }
101 |
102 | article blockquote {
103 | position: relative;
104 | font-size: .8823em;
105 | margin: 20px 0;
106 | padding: 12px 10px;
107 | line-height: 1.4;
108 | color: #999;
109 | background: #fff;
110 | border: 1px solid #ddd
111 | }
112 |
113 | article table {
114 | margin: 15px auto;
115 | color: #464646
116 | }
117 |
118 | article table td,
119 | article table th {
120 | text-align: center;
121 | font-size: 14px;
122 | line-height: 1.5em
123 | }
124 |
125 | article table.border th,
126 | article table.border tr:nth-child(2n) {
127 | background: rgba(100, 100, 100, .1)
128 | }
129 |
130 | article table.border td,
131 | article table.border th {
132 | padding: 5px;
133 | font-size: 12px;
134 | border: 1px solid #d4d4d4
135 | }
136 |
137 | @media only screen and (min-width:375px) {
138 | article {
139 | font-size: 18px;
140 | line-height: 1.7
141 | }
142 | article p {
143 | line-height: 1.7
144 | }
145 | }
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "my-project",
3 | "version": "1.0.0",
4 | "description": "A Vue.js project",
5 | "author": "",
6 | "private": true,
7 | "scripts": {
8 | "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
9 | "start": "npm run dev",
10 | "unit": "jest --config test/unit/jest.conf.js --coverage",
11 | "e2e": "node test/e2e/runner.js",
12 | "test": "npm run unit && npm run e2e",
13 | "lint": "eslint --ext .js,.vue src test/unit test/e2e/specs",
14 | "build": "node build/build.js"
15 | },
16 | "dependencies": {
17 | "babel-polyfill": "^6.26.0",
18 | "framework7": "^2.0.10",
19 | "framework7-icons": "^0.8.9",
20 | "vue": "^2.5.2",
21 | "vue-lazyload": "^1.2.2",
22 | "vue-router": "^3.0.1",
23 | "vuex": "^3.0.1",
24 | "vuex-along": "^1.1.2"
25 | },
26 | "devDependencies": {
27 | "autoprefixer": "^7.1.2",
28 | "babel-core": "^6.22.1",
29 | "babel-eslint": "^8.2.1",
30 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
31 | "babel-jest": "^21.0.2",
32 | "babel-loader": "^7.1.1",
33 | "babel-plugin-dynamic-import-node": "^1.2.0",
34 | "babel-plugin-syntax-jsx": "^6.18.0",
35 | "babel-plugin-transform-es2015-modules-commonjs": "^6.26.0",
36 | "babel-plugin-transform-runtime": "^6.22.0",
37 | "babel-plugin-transform-vue-jsx": "^3.5.0",
38 | "babel-preset-env": "^1.3.2",
39 | "babel-preset-stage-2": "^6.22.0",
40 | "babel-register": "^6.22.0",
41 | "chalk": "^2.0.1",
42 | "chromedriver": "^2.27.2",
43 | "copy-webpack-plugin": "^4.0.1",
44 | "cross-spawn": "^5.0.1",
45 | "css-loader": "^0.28.0",
46 | "eslint": "^4.15.0",
47 | "eslint-config-standard": "^10.2.1",
48 | "eslint-friendly-formatter": "^3.0.0",
49 | "eslint-loader": "^1.7.1",
50 | "eslint-plugin-import": "^2.7.0",
51 | "eslint-plugin-node": "^5.2.0",
52 | "eslint-plugin-promise": "^3.4.0",
53 | "eslint-plugin-standard": "^3.0.1",
54 | "eslint-plugin-vue": "^4.0.0",
55 | "extract-text-webpack-plugin": "^3.0.0",
56 | "file-loader": "^1.1.4",
57 | "friendly-errors-webpack-plugin": "^1.6.1",
58 | "html-webpack-plugin": "^2.30.1",
59 | "jest": "^22.0.4",
60 | "jest-serializer-vue": "^0.3.0",
61 | "nightwatch": "^0.9.12",
62 | "node-notifier": "^5.1.2",
63 | "optimize-css-assets-webpack-plugin": "^3.2.0",
64 | "ora": "^1.2.0",
65 | "portfinder": "^1.0.13",
66 | "postcss-import": "^11.0.0",
67 | "postcss-loader": "^2.0.8",
68 | "postcss-url": "^7.2.1",
69 | "rimraf": "^2.6.0",
70 | "selenium-server": "^3.0.1",
71 | "semver": "^5.3.0",
72 | "shelljs": "^0.7.6",
73 | "uglifyjs-webpack-plugin": "^1.1.1",
74 | "url-loader": "^0.5.8",
75 | "vue-jest": "^1.0.2",
76 | "vue-loader": "^13.3.0",
77 | "vue-style-loader": "^3.0.1",
78 | "vue-template-compiler": "^2.5.2",
79 | "webpack": "^3.6.0",
80 | "webpack-bundle-analyzer": "^2.9.0",
81 | "webpack-dev-server": "^2.9.1",
82 | "webpack-merge": "^2.6.1"
83 | },
84 | "engines": {
85 | "node": ">= 6.0.0",
86 | "npm": ">= 3.0.0"
87 | },
88 | "browserslist": [
89 | "> 1%",
90 | "last 2 versions",
91 | "not ie <= 8"
92 | ]
93 | }
94 |
--------------------------------------------------------------------------------
/src/js/plugin/jquery.lazyload.min.js:
--------------------------------------------------------------------------------
1 | /*! Lazy Load 1.9.3 - MIT license - Copyright 2010-2013 Mika Tuupola */
2 | !function(a,b,c,d){var e=a(b);a.fn.lazyload=function(f){function g(){var b=0;i.each(function(){var c=a(this);if(!j.skip_invisible||c.is(":visible"))if(a.abovethetop(this,j)||a.leftofbegin(this,j));else if(a.belowthefold(this,j)||a.rightoffold(this,j)){if(++b>j.failure_limit)return!1}else c.trigger("appear"),b=0})}var h,i=this,j={threshold:0,failure_limit:0,event:"scroll",effect:"show",container:b,data_attribute:"original",skip_invisible:!0,appear:null,load:null,placeholder:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC"};return f&&(d!==f.failurelimit&&(f.failure_limit=f.failurelimit,delete f.failurelimit),d!==f.effectspeed&&(f.effect_speed=f.effectspeed,delete f.effectspeed),a.extend(j,f)),h=j.container===d||j.container===b?e:a(j.container),0===j.event.indexOf("scroll")&&h.bind(j.event,function(){return g()}),this.each(function(){var b=this,c=a(b);b.loaded=!1,(c.attr("src")===d||c.attr("src")===!1)&&c.is("img")&&c.attr("src",j.placeholder),c.one("appear",function(){if(!this.loaded){if(j.appear){var d=i.length;j.appear.call(b,d,j)}a("
").bind("load",function(){var d=c.attr("data-"+j.data_attribute);c.hide(),c.is("img")?c.attr("src",d):c.css("background-image","url('"+d+"')"),c[j.effect](j.effect_speed),b.loaded=!0;var e=a.grep(i,function(a){return!a.loaded});if(i=a(e),j.load){var f=i.length;j.load.call(b,f,j)}}).attr("src",c.attr("data-"+j.data_attribute))}}),0!==j.event.indexOf("scroll")&&c.bind(j.event,function(){b.loaded||c.trigger("appear")})}),e.bind("resize",function(){g()}),/(?:iphone|ipod|ipad).*os 5/gi.test(navigator.appVersion)&&e.bind("pageshow",function(b){b.originalEvent&&b.originalEvent.persisted&&i.each(function(){a(this).trigger("appear")})}),a(c).ready(function(){g()}),this},a.belowthefold=function(c,f){var g;return g=f.container===d||f.container===b?(b.innerHeight?b.innerHeight:e.height())+e.scrollTop():a(f.container).offset().top+a(f.container).height(),g<=a(c).offset().top-f.threshold},a.rightoffold=function(c,f){var g;return g=f.container===d||f.container===b?e.width()+e.scrollLeft():a(f.container).offset().left+a(f.container).width(),g<=a(c).offset().left-f.threshold},a.abovethetop=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollTop():a(f.container).offset().top,g>=a(c).offset().top+f.threshold+a(c).height()},a.leftofbegin=function(c,f){var g;return g=f.container===d||f.container===b?e.scrollLeft():a(f.container).offset().left,g>=a(c).offset().left+f.threshold+a(c).width()},a.inviewport=function(b,c){return!(a.rightoffold(b,c)||a.leftofbegin(b,c)||a.belowthefold(b,c)||a.abovethetop(b,c))},a.extend(a.expr[":"],{"below-the-fold":function(b){return a.belowthefold(b,{threshold:0})},"above-the-top":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-screen":function(b){return a.rightoffold(b,{threshold:0})},"left-of-screen":function(b){return!a.rightoffold(b,{threshold:0})},"in-viewport":function(b){return a.inviewport(b,{threshold:0})},"above-the-fold":function(b){return!a.belowthefold(b,{threshold:0})},"right-of-fold":function(b){return a.rightoffold(b,{threshold:0})},"left-of-fold":function(b){return!a.rightoffold(b,{threshold:0})}})}(jQuery,window,document);
--------------------------------------------------------------------------------
/src/pages/my/follow-member.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
28 |
29 |
30 |
31 |
32 |
33 |
512人正在关注
34 |
先跑为敬,干了这杯还有下杯
35 |
38 |
39 |
![]()
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
88 |
--------------------------------------------------------------------------------
/src/hiapp-pages/message.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
20 |
21 |
22 |
23 |
24 |
25 |
29 |
30 |
--------------------------------------------------------------------------------
/src/pages/form.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Form Example
5 |
6 |
7 | Name
8 |
9 |
10 |
11 | E-mail
12 |
13 |
14 |
15 | URL
16 |
17 |
18 |
19 | Password
20 |
21 |
22 |
23 | Phone
24 |
25 |
26 |
27 | Gender
28 |
29 |
30 |
31 |
32 |
33 |
34 | Birth date
35 |
36 |
37 |
38 |
39 |
40 |
41 | Slider
42 |
43 |
44 |
45 |
46 |
47 | Textarea
48 |
49 |
50 |
51 | Resizable
52 |
53 |
54 |
55 |
56 | Checkbox group
57 |
58 |
59 |
60 |
61 | Radio buttons group
62 |
63 |
64 |
65 |
66 | Buttons
67 |
68 |
69 | Button
70 | Fill
71 |
72 |
73 | Raised
74 | Raised Fill
75 |
76 |
77 | Round
78 | Round Fill
79 |
80 |
81 | Outline
82 | Outline Round
83 |
84 |
85 | Small
86 | Small Round
87 |
88 |
89 | Small
90 | Small Round
91 |
92 |
93 | Big
94 | Big Fill
95 |
96 |
97 | Big Red
98 | Big Green
99 |
100 |
101 |
102 |
103 |
104 |
107 |
--------------------------------------------------------------------------------
/src/components/card.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
{{data.text}}
14 |
15 |
![]()
16 |
17 |
18 |
28 |
29 |
30 |
31 |
107 |
108 |
--------------------------------------------------------------------------------
/src/hiapp-pages/card.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
12 |
13 |
{{data.text}}
14 |
15 |
![]()
16 |
17 |
18 |
28 |
29 |
30 |
31 |
107 |
108 |
--------------------------------------------------------------------------------
/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import Router from 'vue-router'
3 | //import HelloWorld from '@/components/HelloWorld'
4 |
5 | import HomePage from '@/pages/home.vue';
6 | import IndexPage from '@/pages/index.vue';
7 | import MinePage from '@/pages/mine.vue';
8 | import StoreIndexPage from '@/pages/store-index.vue';
9 | import ChannelPage from '@/pages/channel.vue';
10 | import AttentionPage from '@/pages/attention.vue';
11 |
12 | import NotFoundPage from '@/pages/not-found.vue';
13 |
14 | import ArticleListPage from '@/pages/article-list.vue';
15 | import StoreListPage from '@/pages/store-list.vue';
16 | import CollectionListPage from '@/pages/collection-list.vue';
17 | import CircleListPage from '@/pages/circle-list.vue';
18 |
19 | import ArticleDetailPage from '@/pages/article-detail.vue';
20 | import ArticleCommentPage from '@/pages/article-comment.vue';
21 | import ArticleCommentSubPage from '@/pages/article-comment-sub.vue';
22 | import StoreDetailPage from '@/pages/store-detail.vue';
23 | import CollectionDetailPage from '@/pages/collection-detail.vue';
24 | import CircleDetailPage from '@/pages/circle-detail.vue';
25 | import CirclethemeDetailPage from '@/pages/circletheme-detail.vue';
26 | import CirclethemePostPage from '@/pages/circletheme-post.vue';
27 |
28 | import My_CirclethemePage from '@/pages/my/circletheme.vue';
29 | import My_FavStorePage from '@/pages/my/fav-store.vue';
30 | import My_FavGoodsPage from '@/pages/my/fav-goods.vue';
31 | import My_FavArticlePage from '@/pages/my/fav-article.vue';
32 | import My_FavCirclethemePage from '@/pages/my/fav-circletheme.vue';
33 | import My_FavCollectionPage from '@/pages/my/fav-collection.vue';
34 | import My_FollowCirclePage from '@/pages/my/follow-circle.vue';
35 | import My_FollowMemberPage from '@/pages/my/follow-member.vue';
36 |
37 | Router.prototype.goBack = function () {
38 | this.isBack = true
39 | window.history.go(-1)
40 | }
41 | Vue.use(Router)
42 |
43 |
44 | const router = new Router({
45 | routes: [{
46 | path: "/",
47 | component: HomePage,
48 | },
49 | {
50 | path: "/index/",
51 | component: IndexPage,
52 | },
53 | {
54 | path: "/mine/",
55 | component: MinePage,
56 | },
57 | {
58 | path: '/store-index/',
59 | component: StoreIndexPage,
60 | },
61 | {
62 | path: '/attention/',
63 | component: AttentionPage,
64 | },
65 | {
66 | path: '/channel/id/:id/',
67 | component: ChannelPage,
68 | },
69 | {
70 | path: '/article-list/',
71 | component: ArticleListPage,
72 | },
73 | {
74 | path: '/store-list/',
75 | component: StoreListPage,
76 | },
77 | {
78 | path: '/circle-list/',
79 | component: CircleListPage,
80 | },
81 | {
82 | path: '/collection-list/',
83 | component: CollectionListPage,
84 | },
85 |
86 | {
87 | path: '/article-detail/id/:id/',
88 | component: ArticleDetailPage,
89 | },
90 | {
91 | path: '/article-comment/id/:id/',
92 | component: ArticleCommentPage,
93 | },
94 | {
95 | path: '/article-comment-sub/id/:id/',
96 | component: ArticleCommentSubPage,
97 | },
98 | {
99 | path: '/store-detail/id/:id/',
100 | component: StoreDetailPage,
101 | },
102 | {
103 | path: '/collection-detail/id/:id/',
104 | component: CollectionDetailPage,
105 | },
106 | {
107 | path: '/circle-detail/id/:id/',
108 | component: CircleDetailPage,
109 | },
110 | {
111 | path: '/circletheme-detail/id/:id/',
112 | component: CirclethemeDetailPage,
113 | },
114 | {
115 | path: '/circletheme-post/',
116 | component: CirclethemePostPage,
117 | },
118 |
119 | {
120 | path: '/my/circletheme/',
121 | component: My_CirclethemePage,
122 | },
123 | {
124 | path: '/my/fav-store/',
125 | component: My_FavStorePage,
126 | },
127 | {
128 | path: '/my/fav-goods/',
129 | component: My_FavGoodsPage,
130 | },
131 | {
132 | path: '/my/fav-article/',
133 | component: My_FavArticlePage,
134 | },
135 | {
136 | path: '/my/fav-circletheme/',
137 | component: My_FavCirclethemePage,
138 | },
139 | {
140 | path: '/my/fav-collection/',
141 | component: My_FavCollectionPage,
142 | },
143 | {
144 | path: '/my/follow-circle/',
145 | component: My_FollowCirclePage,
146 | },
147 | {
148 | path: '/my/follow-member/',
149 | component: My_FollowMemberPage,
150 | },
151 |
152 | //{
153 | // path: '/dynamic-route/blog/:blogId/post/:postId/',
154 | // component: DynamicRoutePage,
155 | //},
156 | {
157 | path: '(.*)',
158 | component: NotFoundPage,
159 | },
160 | ]
161 | })
162 |
163 | //百度统计
164 | router.beforeEach((to, from, next) => {
165 | _hmt.push(['_trackPageview', '/v2/#' + to.path])
166 | document.title = to.meta.title || '杏运树趣看'
167 | next()
168 | })
169 |
170 | export default router;
--------------------------------------------------------------------------------
/src/pages/my/fav-collection.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
30 |
31 |
32 | 暂无内容
33 |
34 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
63 |
--------------------------------------------------------------------------------
/src/pages/my/fav-store.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
30 |
31 |
32 | 暂无内容
33 |
34 |
35 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
66 |
--------------------------------------------------------------------------------
/src/hiapp-pages/post.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
112 |
113 |
--------------------------------------------------------------------------------
/src/pages/my/fav-goods.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
30 |
31 |
32 | 暂无内容
33 |
34 |
35 |
54 |
55 |
56 |
59 |
60 |
61 |
62 |
63 |
64 |
67 |
--------------------------------------------------------------------------------
/src/pages/my/fav-article.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
30 |
31 |
32 | 暂无内容
33 |
34 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
103 |
--------------------------------------------------------------------------------
/src/js/f7-base.js:
--------------------------------------------------------------------------------
1 | /**
2 | * 注册vue的framework7基础全局变量与全局方法
3 | *
4 | * @param {Object} Vue
5 | * @param {Object} Framework7
6 | * @param {Object} options
7 | */
8 | exports.install = function(Vue, Framework7, options) {
9 | Vue.prototype.$f7 = {};
10 | Vue.prototype.$$ = {};
11 |
12 | /**
13 | * 实例化f7对象,模仿f7做一些基本的初始化动作
14 | */
15 | Vue.prototype.setF7 = function() {
16 | var self = this;
17 | var app = new Framework7({
18 | theme: 'ios', // Automatic theme detection
19 | lazy: {
20 | threshold: 0,
21 | sequential: false,
22 | //laceholder: 'http://m.cattlepie.com/img/login/login_icon.png',
23 | placeholder: 'static/img/preload.png',
24 | },
25 | dialog: {
26 | // set default title for all dialog shortcuts
27 | title: '杏运树',
28 | // change default "OK" button text
29 | buttonOk: '确定',
30 | buttonCancel: '取消',
31 | },
32 | });
33 | // app.router.off('touchstart');
34 |
35 | this.$f7 = app;
36 | this.$$ = app.$;
37 | // console.log(app)
38 |
39 | //自动初始化
40 | if (this.$$('.infinite-scroll-content').length > 0) {
41 | app.infiniteScroll.create('.infinite-scroll-content');
42 | }
43 | if (this.$$('.ptr-content').length > 0) {
44 | this.$f7.ptr = app.ptr.create('.ptr-content');
45 | }
46 | if (this.$$('.link.back').length > 0) {
47 | this.$$('.link.back').each(function() {
48 | self.$$(this).on('click', function(e) {
49 | self.$router.goBack()
50 | // self.$router.go(-1);
51 | });
52 | });
53 | }
54 |
55 | return app;
56 | };
57 |
58 | //创建gotop按钮并初始化滚动事件
59 | Vue.prototype.$initGotop = function() {
60 | var self = this;
61 | if (this.$$('#tbox').length<1) {
62 | var $li = this.$$('');
63 | $li.appendTo($(document.body)),
64 | $('#gotop').click(function(){
65 | self.$scrollTop(0, 300);
66 | })
67 | }
68 |
69 | self.$rightb();
70 | this.$$('.page-content').scroll(function(e){
71 | self.$rightb();
72 | })
73 | },
74 |
75 | Vue.prototype.$rightb = function() {
76 | h = 200;
77 | t = this.$scrollTop();
78 | // console.log(t)
79 | if(t > h){
80 | //alert("111");
81 | this.$$('#gotop').show();
82 | }else{
83 | this.$$('#gotop').hide();
84 | }
85 | },
86 |
87 | /**
88 | * 基于f7的滚动到顶部
89 | * @param {Object} position
90 | * @param {Object} duration
91 | * @param {Object} callback
92 | */
93 | Vue.prototype.$scrollTop = function(position, duration, callback) {
94 | return this.$$('.page-content').scrollTop(position, duration, callback);
95 | },
96 |
97 | /**
98 | * 基于f7的滚动到固定选择器
99 | * @param {Object} selector
100 | * @param {Object} speed
101 | */
102 | Vue.prototype.$goAnchor = function(selector, speed) {
103 | speed = speed || 300;
104 | let offsetY = this.$$(selector).offset().top + this.$$('.page-content').scrollTop();
105 | this.$scrollTop(offsetY, speed);
106 | },
107 |
108 | /**
109 | * toast方法
110 | *
111 | * @param {Object} text
112 | * @param {Object} timeout
113 | * @param {Object} positon
114 | * @param {Object} closeButton
115 | * @param {Object} icon
116 | */
117 | Vue.prototype.$toast = function(text, timeout, positon, closeButton, icon=null) {
118 | timeout = arguments[1] ? arguments[1] : 3000;
119 | positon = arguments[2] ? arguments[2] : 'bottom';
120 | closeButton = arguments[3] ? arguments[3] : false;
121 | closeButtonText = arguments[4] ? arguments[4] : '关闭';
122 |
123 | var params = {
124 | text: text,
125 | closeTimeout: timeout,
126 | position: positon,
127 | closeButton: closeButton,
128 | closeButtonText: closeButtonText,
129 | closeButtonColor: 'yellow',
130 | };
131 | if(arguments[4] != null && arguments[4] != undefined) {
132 | //self.$theme.ios ? 'star' : 'star',
133 | if (icon) {
134 | params.icon = 'check';
135 | } else {
136 | params.icon = 'info';
137 | }
138 | }
139 |
140 | this.$f7.toast.create(params).open();
141 | }
142 |
143 | Vue.prototype.$toastWithCallback = function() {
144 | var self = this;
145 | // Create toast
146 | if(!self.toastWithCallback) {
147 | self.toastWithCallback = self.$f7.toast.create({
148 | text: 'Callback on close',
149 | closeButton: true,
150 | on: {
151 | close: function() {
152 | self.$f7.dialog.alert('Toast closed');
153 | },
154 | }
155 | });
156 | }
157 | // Open it
158 | self.toastWithCallback.open();
159 | }
160 |
161 | //打开单张图片浏览器
162 | Vue.prototype.$openOnePhoto = function(url) {
163 | var pb = this.$f7.photoBrowser.create({
164 | photos: [url],
165 | theme: 'dark',
166 | type: 'popup', //popup, page, standalone
167 |
168 | navbarOfText: '/',
169 | backLinkText: '',
170 | toolbar: false,
171 | routableModals: false,
172 | });
173 | pb.on('click', function() {
174 | this.close();
175 | });
176 |
177 | pb.open();
178 | return pb;
179 | };
180 |
181 | //创建相册浏览器,不直接打开
182 | Vue.prototype.$createPhotoBrowser = function(_photos) {
183 | var pb = this.$f7.photoBrowser.create({
184 | photos: _photos,
185 | theme: 'dark',
186 | type: 'popup', //popup, page, standalone
187 |
188 | navbarOfText: '/',
189 | backLinkText: '关闭',
190 | routableModals: false,
191 | });
192 | pb.on('click', function() {
193 | this.close();
194 | });
195 |
196 | return pb;
197 | };
198 |
199 | //遮罩层开关
200 | Vue.prototype.$toggleBackdrop = function() {
201 | if('none' == this.$$('.backdrop-in').css('display')) {
202 | this.$$('.backdrop-in').show(500);
203 | } else {
204 | this.$$('.backdrop-in').hide(500);
205 | }
206 | };
207 | };
--------------------------------------------------------------------------------
/src/pages/my/follow-circle.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
28 |
29 |
30 | 暂无内容
31 |
32 |
33 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
107 |
--------------------------------------------------------------------------------
/src/pages/my/circletheme.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
17 |
18 |
19 | 我的生活贴
20 |
21 |
22 |
23 |
24 |
25 | 暂无内容
26 |
27 |
28 |
29 |
30 |
31 |
![]()
32 |
33 |
{{item.member_name}}
34 |
35 |
36 |
37 |
38 |
39 |
42 |
43 |
44 |
![]()
45 |
46 |
47 |
48 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
118 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # vue-f7-circle说明
2 |
3 | > vue-f7-circle是一套基于framework7(http://framework7.io/) + Vue全家桶(Vue2.x + Vue-router2.x + Vuex)的用于实际项目的圈子社交系统。
4 |
5 | > 本项目最初是用framework7自整理的Framework7 Vue项目框架http://framework7.io/vue/ 开发,后来发现返回页面时,容易出现页面被挡住的现象,对照官方文档研究两天无法解决。后转为基于vue,将framework7的核心方法与对象作为vue的全局方法与对象,界面交互api与界面样式,还是用的framework7的,体验效果还不错。
6 |
7 | [项目演示地址 http://m.cattlepie.com/v2/](http://m.cattlepie.com/v2/)
8 |
9 | 项目代码所含功能板块为:
10 | 1. 圈子,帖子
11 | 2. 合集(店铺+文章+圈子组合)
12 | 3. 文章
13 | 4. 店铺
14 |
15 | 本项目依赖服务端接口,服务端接口项目后续将整理上传
16 |
17 | ## main.js
18 | ```js
19 | //vue-lazyload
20 | import VueLazyload from 'vue-lazyload';
21 | Vue.use(VueLazyload, {
22 | preLoad: 1.3,
23 | error: 'static/img/preload.png',
24 | loading: 'static/img/preload.png',
25 | attempt: 2
26 | });
27 |
28 | //引入vue基础框架
29 | import base from './js/base.js';
30 | import config from './js/config.js';
31 | import wap from './js/wap.js';
32 | Vue.use(base, config, wap);
33 |
34 | //引入f7基础框架
35 | //import Framework7 from 'framework7/dist/framework7.esm.bundle.js';
36 | import Framework7 from 'framework7';
37 | import Swiper from 'framework7/dist/components/swiper/swiper.js';
38 | import Popup from 'framework7/dist/components/popup/popup.js';
39 | import Popover from 'framework7/dist/components/popover/popover.js';
40 | import Preloader from 'framework7/dist/components/preloader/preloader.js';
41 | import PullToRefresh from 'framework7/dist/components/pull-to-refresh/pull-to-refresh.js';
42 | import Toast from 'framework7/dist/components/toast/toast.js';
43 | import PhotoBrowser from 'framework7/dist/components/photo-browser/photo-browser.js';
44 | import Dialog from 'framework7/dist/components/dialog/dialog.js';
45 | import Sheet from 'framework7/dist/components/sheet/sheet.js';
46 | import InfiniteScroll from 'framework7/dist/components/infinite-scroll/infinite-scroll.js';
47 |
48 | Framework7.use([Swiper,Popup,Popover,Preloader,PullToRefresh,Toast,PhotoBrowser,Dialog,Sheet,InfiniteScroll]);
49 |
50 | import F7Base from './js/f7-base.js'
51 | Vue.use(F7Base, Framework7);
52 |
53 |
54 | var _hmt = window._hmt || []
55 |
56 | /* eslint-disable no-new */
57 | new Vue({
58 | el: '#app',
59 | store,
60 | router,
61 | components: { App },
62 | template: ''
63 | })
64 | ```
65 | ## f7全局对象与方法注册
66 | ```js
67 | /**
68 | * 注册vue的framework7基础全局变量与全局方法
69 | *
70 | * @param {Object} Vue
71 | * @param {Object} Framework7
72 | * @param {Object} options
73 | */
74 | exports.install = function(Vue, Framework7, options) {
75 | Vue.prototype.$f7 = {};
76 | Vue.prototype.$$ = {};
77 |
78 | /**
79 | * 实例化f7对象,模仿f7做一些基本的初始化动作
80 | */
81 | Vue.prototype.setF7 = function() {
82 | var self = this;
83 | var app = new Framework7({
84 | theme: 'ios', // Automatic theme detection
85 | lazy: {
86 | threshold: 0,
87 | sequential: false,
88 | //laceholder: 'http://m.cattlepie.com/img/login/login_icon.png',
89 | placeholder: 'static/img/preload.png',
90 | },
91 | dialog: {
92 | // set default title for all dialog shortcuts
93 | title: '杏运树',
94 | // change default "OK" button text
95 | buttonOk: '确定',
96 | buttonCancel: '取消',
97 | },
98 | });
99 | // app.router.off('touchstart');
100 |
101 | this.$f7 = app;
102 | this.$$ = app.$;
103 | // console.log(app)
104 |
105 | //自动初始化
106 | if (this.$$('.infinite-scroll-content').length > 0) {
107 | app.infiniteScroll.create('.infinite-scroll-content');
108 | }
109 | if (this.$$('.ptr-content').length > 0) {
110 | this.$f7.ptr = app.ptr.create('.ptr-content');
111 | }
112 | if (this.$$('.link.back').length > 0) {
113 | this.$$('.link.back').each(function() {
114 | self.$$(this).on('click', function(e) {
115 | self.$router.goBack()
116 | // self.$router.go(-1);
117 | });
118 | });
119 | }
120 |
121 | return app;
122 | };
123 |
124 | /**
125 | * 基于f7的滚动到顶部
126 | * @param {Object} position
127 | * @param {Object} duration
128 | * @param {Object} callback
129 | */
130 | Vue.prototype.$scrollTop = function(position, duration, callback) {
131 | return this.$$('.page-content').scrollTop(position, duration, callback);
132 | },
133 |
134 | /**
135 | * 基于f7的滚动到固定选择器
136 | * @param {Object} selector
137 | * @param {Object} speed
138 | */
139 | Vue.prototype.$goAnchor = function(selector, speed) {
140 | speed = speed || 300;
141 | let offsetY = this.$$(selector).offset().top + this.$$('.page-content').scrollTop();
142 | this.$scrollTop(offsetY, speed);
143 | }
144 | }
145 | ```
146 | ## 截图演示
147 | 
148 | 
149 | 
150 | 
151 | 
152 | 
153 | 
154 | 
155 | 
156 | 
157 | 
158 | 
159 | 
160 |
161 | ## Build Setup
162 |
163 | ``` bash
164 | # install dependencies
165 | npm install
166 |
167 | # serve with hot reload at localhost:8080
168 | npm run dev
169 |
170 | # build for production with minification
171 | npm run build
172 |
173 | # build for production and view the bundle analyzer report
174 | npm run build --report
175 |
176 | # run unit tests
177 | npm run unit
178 |
179 | # run e2e tests
180 | npm run e2e
181 |
182 | # run all tests
183 | npm test
184 | ```
185 |
186 |
187 |
--------------------------------------------------------------------------------
/src/pages/my/fav-circletheme.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
14 |
15 |
16 |
30 |
31 |
32 |
33 |
34 | 暂无内容
35 |
36 |
37 |
38 |
39 |
![]()
40 |
41 |
{{item.member_name}}
42 |
43 |
44 |
45 |
46 |
49 |
50 |
51 |
![]()
52 |
53 |
54 |
55 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
128 |
--------------------------------------------------------------------------------
/src/pages/circle-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
24 |
25 |
45 |
46 |
48 |
52 |
53 |
54 | 暂无内容
55 |
56 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
128 |
--------------------------------------------------------------------------------
/src/pages/collection-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
22 |
23 |
24 |
42 |
43 |
45 |
49 |
50 |
51 | 暂无内容
52 |
53 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
118 |
--------------------------------------------------------------------------------
/src/pages/article-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
24 |
25 |
44 |
45 |
47 |
51 |
52 |
53 | 暂无内容
54 |
55 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
97 |
--------------------------------------------------------------------------------
/src/pages/store-list.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
24 |
25 |
44 |
45 |
47 |
48 | 暂无内容
49 |
50 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
109 |
--------------------------------------------------------------------------------
/src/css/webuploader-demo.min.css:
--------------------------------------------------------------------------------
1 | #container {
2 | color: #838383;
3 | font-size: 12px
4 | }
5 |
6 | #uploader .queueList {
7 | margin: 20px;
8 | border: 3px dashed #e6e6e6
9 | }
10 |
11 | #uploader .queueList.filled {
12 | padding: 17px;
13 | margin: 0;
14 | border: 3px dashed transparent
15 | }
16 |
17 | #uploader .queueList.webuploader-dnd-over {
18 | border: 3px dashed #999
19 | }
20 |
21 | #uploader p {
22 | margin: 0
23 | }
24 |
25 | .element-invisible {
26 | position: absolute !important;
27 | clip: rect(1px 1px 1px 1px);
28 | clip: rect(1px, 1px, 1px, 1px)
29 | }
30 |
31 | #uploader .placeholder {
32 | min-height: 100px;
33 | padding-top: 40px;
34 | text-align: center;
35 | color: #ccc;
36 | font-size: 18px;
37 | position: relative
38 | }
39 |
40 | #uploader .placeholder .webuploader-pick {
41 | font-size: 18px;
42 | background: #00b7ee;
43 | border-radius: 3px;
44 | line-height: 44px;
45 | padding: 0 30px;
46 | *width: 120px;
47 | color: #fff;
48 | display: inline-block;
49 | margin: 0 auto 20px;
50 | cursor: pointer;
51 | box-shadow: 0 1px 1px rgba(0, 0, 0, .1)
52 | }
53 |
54 | #uploader .placeholder .webuploader-pick-hover {
55 | background: #00a2d4
56 | }
57 |
58 | #uploader .placeholder .flashTip {
59 | color: #666;
60 | font-size: 12px;
61 | position: absolute;
62 | width: 100%;
63 | text-align: center;
64 | bottom: 20px
65 | }
66 |
67 | #uploader .placeholder .flashTip a {
68 | color: #0785d1;
69 | text-decoration: none
70 | }
71 |
72 | #uploader .placeholder .flashTip a:hover {
73 | text-decoration: underline
74 | }
75 |
76 | #uploader .filelist {
77 | list-style: none;
78 | margin: 0;
79 | padding: 0
80 | }
81 |
82 | #uploader .filelist:after {
83 | content: '';
84 | display: block;
85 | width: 0;
86 | height: 0;
87 | overflow: hidden;
88 | clear: both
89 | }
90 |
91 | #uploader .filelist li {
92 | width: 110px;
93 | height: 110px;
94 | text-align: center;
95 | margin: 0 8px 20px 0;
96 | position: relative;
97 | display: inline;
98 | float: left;
99 | overflow: hidden;
100 | font-size: 12px
101 | }
102 |
103 | #uploader .filelist li p.log {
104 | position: relative;
105 | top: -45px
106 | }
107 |
108 | #uploader .filelist li p.title {
109 | position: absolute;
110 | left: 0;
111 | width: 100%;
112 | overflow: hidden;
113 | white-space: nowrap;
114 | text-overflow: ellipsis;
115 | top: 5px;
116 | text-indent: 5px;
117 | text-align: left
118 | }
119 |
120 | #uploader .filelist li p.progress {
121 | position: absolute;
122 | width: 100%;
123 | bottom: 0;
124 | left: 0;
125 | height: 8px;
126 | overflow: hidden;
127 | z-index: 50;
128 | margin: 0;
129 | border-radius: 0;
130 | background: 0 0;
131 | -webkit-box-shadow: 0 0 0
132 | }
133 |
134 | #uploader .filelist li p.progress span {
135 | display: none;
136 | overflow: hidden;
137 | width: 0;
138 | height: 100%;
139 | -webit-transition: width 200ms linear;
140 | -moz-transition: width 200ms linear;
141 | -o-transition: width 200ms linear;
142 | -ms-transition: width 200ms linear;
143 | transition: width 200ms linear;
144 | -webkit-animation: progressmove 2s linear infinite;
145 | -moz-animation: progressmove 2s linear infinite;
146 | -o-animation: progressmove 2s linear infinite;
147 | -ms-animation: progressmove 2s linear infinite;
148 | animation: progressmove 2s linear infinite;
149 | -webkit-transform: translateZ(0)
150 | }
151 |
152 | @-webkit-keyframes progressmove {
153 | 0% {
154 | background-position: 0 0
155 | }
156 | 100% {
157 | background-position: 17px 0
158 | }
159 | }
160 |
161 | @-moz-keyframes progressmove {
162 | 0% {
163 | background-position: 0 0
164 | }
165 | 100% {
166 | background-position: 17px 0
167 | }
168 | }
169 |
170 | @keyframes progressmove {
171 | 0% {
172 | background-position: 0 0
173 | }
174 | 100% {
175 | background-position: 17px 0
176 | }
177 | }
178 |
179 | #uploader .filelist li p.imgWrap {
180 | position: relative;
181 | z-index: 2;
182 | line-height: 110px;
183 | vertical-align: middle;
184 | overflow: hidden;
185 | width: 110px;
186 | height: 110px;
187 | -webkit-transform-origin: 50% 50%;
188 | -moz-transform-origin: 50% 50%;
189 | -o-transform-origin: 50% 50%;
190 | -ms-transform-origin: 50% 50%;
191 | transform-origin: 50% 50%;
192 | -webit-transition: 200ms ease-out;
193 | -moz-transition: 200ms ease-out;
194 | -o-transition: 200ms ease-out;
195 | -ms-transition: 200ms ease-out;
196 | transition: 200ms ease-out
197 | }
198 |
199 | #uploader .filelist li img {
200 | width: 100%
201 | }
202 |
203 | #uploader .filelist li p.error {
204 | background: #f43838;
205 | color: #fff;
206 | position: absolute;
207 | bottom: 0;
208 | left: 0;
209 | height: 28px;
210 | line-height: 28px;
211 | width: 100%;
212 | z-index: 100
213 | }
214 |
215 | #uploader .filelist li .success {
216 | display: block;
217 | position: absolute;
218 | left: 0;
219 | bottom: 0;
220 | height: 40px;
221 | width: 100%;
222 | z-index: 200;
223 | }
224 |
225 | #uploader .filelist div.file-panel {
226 | position: absolute;
227 | height: 0;
228 | filter: progid:DXImageTransform.Microsoft.gradient(GradientType=0, startColorstr='#80000000', endColorstr='#80000000') \0;
229 | background: rgba(0, 0, 0, .5);
230 | width: 100%;
231 | top: 0;
232 | left: 0;
233 | overflow: hidden;
234 | z-index: 300
235 | }
236 |
237 | #uploader .filelist div.file-panel span {
238 | width: 24px;
239 | height: 24px;
240 | display: inline;
241 | float: right;
242 | text-indent: -9999px;
243 | overflow: hidden;
244 | margin: 5px 1px 1px;
245 | cursor: pointer
246 | }
247 |
248 | #uploader .filelist div.file-panel span.rotateLeft {
249 | background-position: 0 -24px
250 | }
251 |
252 | #uploader .filelist div.file-panel span.rotateLeft:hover {
253 | background-position: 0 0
254 | }
255 |
256 | #uploader .filelist div.file-panel span.rotateRight {
257 | background-position: -24px -24px
258 | }
259 |
260 | #uploader .filelist div.file-panel span.rotateRight:hover {
261 | background-position: -24px 0
262 | }
263 |
264 | #uploader .filelist div.file-panel span.cancel {
265 | background-position: -48px -24px
266 | }
267 |
268 | #uploader .filelist div.file-panel span.cancel:hover {
269 | background-position: -48px 0
270 | }
271 |
272 | #uploader .statusBar {
273 | height: 63px;
274 | border-top: 1px solid #dadada;
275 | padding: 0 20px;
276 | line-height: 63px;
277 | vertical-align: middle;
278 | position: relative
279 | }
280 |
281 | #uploader .statusBar .progress {
282 | border: 1px solid #1483d8;
283 | width: 198px;
284 | background: #fff;
285 | height: 18px;
286 | display: inline-block;
287 | text-align: center;
288 | line-height: 20px;
289 | color: #6dbfff;
290 | position: relative;
291 | margin: 0 10px 0 0
292 | }
293 |
294 | #uploader .statusBar .progress span.percentage {
295 | width: 0;
296 | height: 100%;
297 | left: 0;
298 | top: 0;
299 | background: #1483d8;
300 | position: absolute
301 | }
302 |
303 | #uploader .statusBar .progress span.text {
304 | position: relative;
305 | z-index: 10
306 | }
307 |
308 | #uploader .statusBar .info {
309 | display: inline-block;
310 | font-size: 14px;
311 | color: #666
312 | }
313 |
314 | #uploader .statusBar .btns {
315 | position: absolute;
316 | top: 10px;
317 | right: 20px;
318 | line-height: 40px
319 | }
320 |
321 | #filePicker2 {
322 | display: inline-block;
323 | float: left
324 | }
325 |
326 | #uploader .statusBar .btns .uploadBtn, #uploader .statusBar .btns .uploadBtn.state-paused, #uploader .statusBar .btns .uploadBtn.state-uploading, #uploader .statusBar .btns .webuploader-pick {
327 | background: #fff;
328 | border: 1px solid #cfcfcf;
329 | color: #565656;
330 | padding: 0 18px;
331 | display: inline-block;
332 | border-radius: 3px;
333 | margin-left: 10px;
334 | cursor: pointer;
335 | font-size: 14px;
336 | float: left
337 | }
338 |
339 | #uploader .statusBar .btns .uploadBtn.state-paused:hover, #uploader .statusBar .btns .uploadBtn.state-uploading:hover, #uploader .statusBar .btns .uploadBtn:hover, #uploader .statusBar .btns .webuploader-pick-hover {
340 | background: #f0f0f0
341 | }
342 |
343 | #uploader .statusBar .btns .uploadBtn {
344 | background: #00b7ee;
345 | color: #fff;
346 | border-color: transparent
347 | }
348 |
349 | #uploader .statusBar .btns .uploadBtn:hover {
350 | background: #00a2d4
351 | }
352 |
353 | #uploader .statusBar .btns .uploadBtn.disabled {
354 | pointer-events: none;
355 | opacity: .6
356 | }
357 |
--------------------------------------------------------------------------------
/src/store/actions.js:
--------------------------------------------------------------------------------
1 | import wap from '../js/wap.js'
2 |
3 | /**
4 | * 顶/取消顶 各类资源对象
5 | */
6 | export function upItem({commit}, {objType, objId, type, callback = () => {} }) {
7 | let mutation = '';
8 | let apiUpType = '';
9 | switch(objType) {
10 | case 'article':
11 | mutation = 'CHANGE_ARTICLE';
12 | apiUpType = 'article';
13 | break
14 | case 'article_reply':
15 | mutation = 'CHANGE_ARTICLE_REPLY';
16 | apiUpType = 'article_reply';
17 | break
18 | case 'theme':
19 | mutation = 'CHANGE_THEME';
20 | apiUpType = 'theme';
21 | break
22 | case 'theme_reply':
23 | mutation = 'CHANGE_THEME_REPLY';
24 | apiUpType = 'theme_reply';
25 | break
26 | }
27 |
28 | let data = {
29 | obj_id: objId,
30 | up_type: apiUpType,
31 | };
32 | let apiUri = type == 'up' ? 'api/user/memberup/up' : 'api/user/memberup/cancelUp';
33 | //提前改变本地状态
34 | commit(mutation, {
35 | mid: data.obj_id,
36 | type: type //up or unup
37 | });
38 |
39 | wap.doajax(apiUri, data, function(res) {
40 | if(res.code != '200' && res.code != '202') {
41 | //服务端处理失败,反向改变本地状态
42 | commit(mutation, {
43 | mid: data.obj_id,
44 | type: type == 'up' ? 'unup' : 'up' //up or unup
45 | });
46 | }
47 |
48 | callback(res);
49 | }, 'v1', true);
50 | }
51 |
52 | /**
53 | * 收藏/取消收藏 各类资源对象
54 | */
55 | export function likeItem({commit}, {objType, objId, type, callback = () => {} }) {
56 | let mutation = '';
57 | let apiUpType = '';
58 | switch(objType) {
59 | case 'article':
60 | mutation = 'CHANGE_ARTICLE';
61 | apiUpType = 'article';
62 | break;
63 | case 'theme':
64 | mutation = 'CHANGE_THEME';
65 | apiUpType = 'theme';
66 | break;
67 | case 'collection':
68 | mutation = 'CHANGE_COLLECTION';
69 | apiUpType = 'collection';
70 | break;
71 | case 'store':
72 | mutation = 'CHANGE_STORE';
73 | apiUpType = 'store';
74 | break;
75 | case 'goods':
76 | mutation = 'CHANGE_GOODS';
77 | apiUpType = 'goods';
78 | break;
79 | }
80 |
81 | let data = {
82 | obj_id: objId,
83 | fav_type: apiUpType,
84 | };
85 | let apiUri = type == 'like' ? 'api/user/memberfav/fav' : 'api/user/memberfav/cancelFav';
86 | //提前改变本地状态
87 | commit(mutation, {
88 | mid: data.obj_id,
89 | type: type //like or unlike
90 | });
91 |
92 | wap.doajax(apiUri, data, function(res) {
93 | if(res.code != '200' && res.code != '202') {
94 | //服务端处理失败,反向改变本地状态
95 | commit(mutation, {
96 | mid: data.obj_id,
97 | type: type == 'like' ? 'unlike' : 'like' //up or unup
98 | });
99 | }
100 |
101 | callback(res);
102 | }, 'v1', true);
103 | }
104 |
105 | /**
106 | * 文章动态变化数据 服务端获取,并写入state
107 | */
108 | export function getArticleMut({commit}, {data={}, callback = () => {} }) {
109 | wap.getajax('api/user/cmsarticle/mutDetail', data, function(res, fromCache) {
110 | if(res.status == 'success') {
111 | let _item = {
112 | article_id : res.data.article_id,
113 | article_like_count : res.data.article_like_count,
114 | article_click: res.data.article_click,
115 | article_up: res.data.article_up,
116 | article_comment_count: res.data.article_comment_count,
117 | liked: res.data.liked || 0,
118 | uped: res.data.uped || 0,
119 | };
120 | commit('ADD_ARTICLES_MUT', {items: [_item]});
121 | }
122 | callback(res);
123 |
124 | }, 'v1', true, 0);
125 | }
126 |
127 | /**
128 | * 文章点击服务端处理,并写入state
129 | */
130 | export function clickArticle({commit}, {article_id, callback = () => {} }) {
131 | let data = {article_id: article_id};
132 | wap.getajax('api/user/cmsarticle/click', data, function(res) {
133 | if(res.status == 'success') {
134 | commit('CHANGE_ARTICLE', {
135 | mid: article_id,
136 | type: 'click',
137 | });
138 | }
139 | callback();
140 | }, 'v1', true);
141 | }
142 |
143 | /**
144 | * 文章回复列表数据 服务端获取,并将可变化数据写入state
145 | */
146 | export function getArticleReplies({commit}, {data={}, cacheTime=0, callback = () => {} }) {
147 | wap.getajax('api/user/articlereply/searchList', data, function(res, fromCache) {
148 | // debugger
149 | if(res.status == 'success') {
150 | commit('ADD_ARTICLE_REPLIES_MUT', {items: res.data.datalist});
151 | callback(res);
152 | }
153 |
154 | }, 'v1', true, cacheTime);
155 | }
156 |
157 | /**
158 | * 圈子数据 服务端获取,并将可变化数据写入state
159 | */
160 | export function getCircleMut({commit,getters}, {circleID, callback = () => {} }) {
161 | // debugger
162 | //详情
163 | wap.getajax('api/user/circle/detail?circle_id=' + circleID, {}, function(res) {
164 | if(!wap.checkLogin(false)) {
165 | callback(res);
166 | return;
167 | }
168 |
169 | //关注状态等动态数据
170 | let mutCircle = getters.getMutCircle(circleID, 0);
171 | if (undefined != mutCircle) {
172 | callback(res);
173 | return;
174 | }
175 |
176 | //如果不存在,则重新获取变化数据
177 | wap.getajax('api/user/circle/getJoinState?circle_id=' + circleID, {}, function(res2, fromCache) {
178 | if(res2.status == 'success') {
179 | // if (!fromCache) {
180 | let _item = {
181 | circle_id: res.data.circle_id,
182 | circle_thcount: res.data.circle_thcount,
183 | circle_mcount: res.data.circle_mcount,
184 | joined: res2.data.join_state[0] == 1 ? 1 : 0,
185 | };
186 | commit('ADD_CIRCLES_MUT', {items: [_item]});
187 | // }
188 | callback(res);
189 | }
190 | }, 'v1', true, 0);
191 |
192 | }, 'v1', true, 3600);
193 |
194 | }
195 |
196 | /**
197 | * 加入、退出圈子 服务端处理,并写入state
198 | */
199 | export function joinCircle({commit}, {circle_id,circle_name, type, callback = () => {} }) {
200 | let data = {
201 | circle_id: circle_id,
202 | circle_name: circle_name,
203 | };
204 |
205 | let apiUri = type == 'join' ? 'api/user/circle/join' : 'api/user/circle/quit';
206 |
207 | wap.doajax(apiUri, data, function(res) {
208 | if(res.code == '200' || res.code == '403') {
209 | commit('CHANGE_CIRCLE', {
210 | mid: data.circle_id,
211 | type: type //join or unjoin
212 | });
213 | }
214 |
215 | callback(res);
216 | }, 'v1', true);
217 | }
218 |
219 | /**
220 | * 主题帖数据 服务端获取,并将可变化数据写入state
221 | */
222 | export function getThemes({commit}, {data={}, cacheTime=0, callback = () => {} }) {
223 | wap.getajax('api/user/circletheme/searchList', data, function(res, fromCache) {
224 | if(res.status == 'success') {
225 | commit('ADD_THEMES_MUT', {items: res.data.datalist});
226 | callback(res);
227 | }
228 |
229 | }, 'v1', true, cacheTime);
230 | }
231 |
232 |
233 | /**
234 | * 帖子变化数据 服务端获取,并写入state
235 | */
236 | export function getThemeMut({commit}, {data={}, callback = () => {} }) {
237 | wap.getajax('api/user/circletheme/mutDetail', data, function(res, fromCache) {
238 | if(res.status == 'success') {
239 | let _item = {
240 | theme_id : res.data.theme_id,
241 | theme_like_count : res.data.theme_like_count,
242 | theme_up_count: res.data.theme_up_count,
243 | theme_commentcount: res.data.theme_commentcount,
244 | liked: res.data.liked || 0,
245 | uped: res.data.uped || 0,
246 | };
247 | commit('ADD_THEMES_MUT', {items: [_item]});
248 | }
249 | callback(res);
250 |
251 | }, 'v1', true, 0);
252 | }
253 |
254 |
255 | /**
256 | * 文章回复列表数据 服务端获取,并将可变化数据写入state
257 | */
258 | export function getThemeReplies({commit}, {data={}, cacheTime=0, callback = () => {} }) {
259 | wap.getajax('api/user/circlethreply/searchList', data, function(res, fromCache) {
260 | // debugger
261 | if(res.status == 'success') {
262 | commit('ADD_THEME_REPLIES_MUT', {items: res.data.datalist});
263 | callback(res);
264 | }
265 |
266 | }, 'v1', true, cacheTime);
267 | }
268 |
269 |
270 | /**
271 | * 主题帖数据 服务端获取,并将可变化数据写入state
272 | */
273 | export function getCollections({commit}, {data={}, cacheTime=0, callback = () => {} }) {
274 | wap.getajax('api/user/collection/searchList', data, function(res, fromCache) {
275 | if(res.status == 'success') {
276 | commit('ADD_COLLECTIONS_MUT', {items: res.data.datalist});
277 | callback(res);
278 | }
279 |
280 | }, 'v1', true, cacheTime);
281 | }
282 |
283 |
284 | /**
285 | * 帖子变化数据 服务端获取,并写入state
286 | */
287 | export function getCollectionMut({commit}, {data={}, callback = () => {} }) {
288 | wap.getajax('api/user/collection/mutDetail', data, function(res, fromCache) {
289 | if(res.status == 'success') {
290 | let _item = {
291 | cl_id : res.data.cl_id,
292 | cl_like_count : res.data.cl_like_count,
293 | uped: res.data.uped,
294 | liked: res.data.liked,
295 | };
296 | commit('ADD_COLLECTIONS_MUT', {items: [_item]});
297 | }
298 | callback(res);
299 |
300 | }, 'v1', true, 300);
301 | }
302 |
303 |
304 |
305 | /**
306 | * 帖子变化数据 服务端获取,并写入state
307 | */
308 | export function getStoreMut({commit}, {data={}, callback = () => {} }) {
309 | wap.getajax('api/user/store/mutDetail', data, function(res, fromCache) {
310 | if(res.status == 'success') {
311 | let _item = {
312 | store_id : res.data.store_id,
313 | liked: res.data.liked || 0,
314 | uped: res.data.uped || 0,
315 | };
316 | commit('ADD_COLLECTIONS_MUT', {items: [_item]});
317 | }
318 | callback(res);
319 |
320 | }, 'v1', true, 300);
321 | }
--------------------------------------------------------------------------------
/src/store/mutations.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 |
3 | export default {
4 | SET_SCROLL_TOP(state, {k,v} ) {
5 | Vue.set(state.position, k, v);
6 | // state.position = val;
7 | },
8 |
9 | /**
10 | * 文章变化数据 记录到state
11 | */
12 | ADD_ARTICLES_MUT(state, {
13 | items
14 | }) {
15 | // for (var i=0; i p.article_id === items[i].article_id);
17 | // if (undefined == item) {
18 | // state.stateArticles.push(items[i]);
19 | // }
20 | // }
21 | for(var i = 0; i < items.length; i++) {
22 | let k = 'k' + items[i].article_id;
23 | Vue.set(state.mutArticlesState, k, items[i]);
24 | }
25 | },
26 |
27 | /**
28 | * 文章 单项记录值 修改
29 | */
30 | CHANGE_ARTICLE(state, {
31 | mid,
32 | type,
33 | val=1
34 | }) {
35 | let item = state.mutArticlesState['k' + mid];
36 | let update = {}
37 | switch(type) {
38 | case 'up':
39 | update.article_up = item.article_up + val
40 | update.uped = true
41 | break;
42 | case 'unup':
43 | update.article_up = item.article_up - val
44 | update.uped = false
45 | break;
46 | case 'like':
47 | update.article_like_count = item.article_like_count + val
48 | update.liked = true
49 | break;
50 | case 'unlike':
51 | update.article_like_count = item.article_like_count - val
52 | update.liked = false
53 | break;
54 | case 'click':
55 | update.article_click = item.article_click + 1
56 | break;
57 | case 'reply':
58 | update.article_comment_count = item.article_comment_count + 1
59 | break;
60 | }
61 |
62 | // Yes, Object.assign can update state and UI component at same time.
63 | item = Object.assign(item, update)
64 | },
65 |
66 | /**
67 | * 文章回复 的变化数据 记录到state
68 | */
69 | ADD_ARTICLE_REPLIES_MUT(state, {
70 | items, cover=0
71 | }) {
72 | for(var i = 0; i < items.length; i++) {
73 | let k = 'k' + items[i].reply_id;
74 | //如果state里有该项数据,则忽略不覆盖
75 | if (undefined !== state.mutArticleRepliesState[k] && !cover) {
76 | continue;
77 | }
78 |
79 | let item = {
80 | reply_up: items[i].reply_up,
81 | uped: items[i].uped || 0,
82 | };
83 | Vue.set(state.mutArticleRepliesState, k, item);
84 | }
85 | },
86 |
87 | /**
88 | * 文章回复 的记录值 修改
89 | */
90 | CHANGE_ARTICLE_REPLY(state, {
91 | mid,
92 | type
93 | }) {
94 | let item = state.mutArticleRepliesState['k' + mid];
95 | let update = {}
96 | switch(type) {
97 | case 'up':
98 | update.reply_up = item.reply_up + 1
99 | update.uped = true
100 | break
101 | case 'unup':
102 | update.reply_up = item.reply_up - 1
103 | update.uped = false
104 | break
105 | }
106 |
107 | // Yes, Object.assign can update state and UI component at same time.
108 | item = Object.assign(item, update)
109 | },
110 |
111 | /**
112 | * 帖子 的变化数据 记录到state
113 | */
114 | ADD_COLLECTIONS_MUT(state, {
115 | items, cover=0
116 | }) {
117 | for(var i = 0; i < items.length; i++) {
118 | let k = 'k' + items[i].cl_id;
119 | //如果state里有该项数据,则忽略不覆盖
120 | if (undefined !== state.mutCollectionsState[k] && !cover) {
121 | continue;
122 | }
123 |
124 | let item = {
125 | cl_like_count: items[i].cl_like_count,
126 | liked: items[i].liked || 0,
127 | };
128 | Vue.set(state.mutCollectionsState, k, item);
129 | }
130 | },
131 |
132 | /**
133 | * 帖子 的变化数据 记录到state
134 | */
135 | CHANGE_COLLECTION(state, {
136 | mid,
137 | type
138 | }) {
139 | let item = state.mutCollectionsState['k' + mid];
140 | let update = {}
141 | switch(type) {
142 | case 'like':
143 | update.cl_like_count = item.cl_like_count + 1
144 | update.liked = true
145 | break
146 | case 'unlike':
147 | update.cl_like_count = item.cl_like_count - 1
148 | update.liked = false
149 | break
150 | }
151 |
152 | // Yes, Object.assign can update state and UI component at same time.
153 | item = Object.assign(item, update)
154 | },
155 |
156 |
157 | /**
158 | * 圈子 的变化数据 记录到state
159 | */
160 | ADD_CIRCLES_MUT(state, {
161 | items
162 | }) {
163 | for(var i = 0; i < items.length; i++) {
164 | let k = 'k' + items[i].circle_id;
165 | //如果state里有该项数据,则忽略不覆盖
166 | if (undefined !== state.mutCirclesState[k]) {
167 | continue;
168 | }
169 |
170 | Vue.set(state.mutCirclesState, k, items[i]);
171 | }
172 | },
173 |
174 | /**
175 | * 圈子 的记录值 修改
176 | */
177 | CHANGE_CIRCLE(state, {
178 | mid,
179 | type
180 | }) {
181 | let item = state.mutCirclesState['k' + mid];
182 | let update = {}
183 | switch(type) {
184 | case 'join':
185 | update.circle_mcount = item.circle_mcount + 1
186 | update.joined = true
187 | break
188 | case 'unjoin':
189 | update.circle_mcount = item.circle_mcount - 1
190 | update.joined = false
191 | break
192 | }
193 |
194 | // Yes, Object.assign can update state and UI component at same time.
195 | item = Object.assign(item, update)
196 | },
197 |
198 | /**
199 | * 帖子 的变化数据 记录到state
200 | */
201 | ADD_THEMES_MUT(state, {
202 | items, cover=0
203 | }) {
204 | for(var i = 0; i < items.length; i++) {
205 | let k = 'k' + items[i].theme_id;
206 | //如果state里有该项数据,则忽略不覆盖
207 | if (undefined !== state.mutThemesState[k] && !cover) {
208 | continue;
209 | }
210 |
211 | let item = {
212 | theme_like_count: items[i].theme_like_count,
213 | theme_up_count: items[i].theme_up_count,
214 | theme_commentcount: items[i].theme_commentcount,
215 | liked: items[i].liked || 0,
216 | uped: items[i].uped || 0,
217 | };
218 | Vue.set(state.mutThemesState, k, item);
219 | }
220 | },
221 |
222 | /**
223 | * 帖子 的变化数据 记录到state
224 | */
225 | CHANGE_THEME(state, {
226 | mid,
227 | type,
228 | val
229 | }) {
230 | let item = state.mutThemesState['k' + mid];
231 | let update = {}
232 | switch(type) {
233 | case 'up':
234 | update.theme_up_count = item.theme_up_count + 1
235 | update.uped = true
236 | break
237 | case 'unup':
238 | update.theme_up_count = item.theme_up_count - 1
239 | update.uped = false
240 | break
241 | case 'like':
242 | update.theme_like_count = item.theme_like_count + 1
243 | update.liked = true
244 | break
245 | case 'unlike':
246 | update.theme_like_count = item.theme_like_count - 1
247 | update.liked = false
248 | break
249 | case 'reply':
250 | update.theme_commentcount = item.theme_commentcount + 1
251 | break
252 | case 'uped':
253 | update.uped = item.val;
254 | break
255 | case 'liked':
256 | update.liked = item.val;
257 | break
258 | }
259 |
260 | // Yes, Object.assign can update state and UI component at same time.
261 | item = Object.assign(item, update)
262 | },
263 |
264 | /**
265 | * 帖子回复 的变化数据 记录到state
266 | */
267 | ADD_THEME_REPLIES_MUT(state, {
268 | items
269 | }) {
270 | for(var i = 0; i < items.length; i++) {
271 | let k = 'k' + items[i].reply_id;
272 | //如果state里有该项数据,则忽略不覆盖
273 | if (undefined !== state.mutThemeRepliesState[k]) {
274 | continue;
275 | }
276 |
277 | let item = {
278 | reply_up: items[i].reply_up,
279 | uped: 0,
280 | };
281 | Vue.set(state.mutThemeRepliesState, k, item);
282 | }
283 | },
284 |
285 | /**
286 | * 帖子回复 的记录值 修改
287 | */
288 | CHANGE_THEME_REPLY(state, {
289 | mid,
290 | type
291 | }) {
292 | let item = state.mutThemeRepliesState['k' + mid];
293 | let update = {}
294 | switch(type) {
295 | case 'up':
296 | update.reply_up = item.reply_up + 1
297 | update.uped = true
298 | break
299 | case 'unup':
300 | update.reply_up = item.reply_up - 1
301 | update.uped = false
302 | break
303 | }
304 |
305 | // Yes, Object.assign can update state and UI component at same time.
306 | item = Object.assign(item, update)
307 | },
308 |
309 | /**
310 | * 帖子 的变化数据 记录到state
311 | */
312 | ADD_STORES_MUT(state, {
313 | items, cover=0
314 | }) {
315 | for(var i = 0; i < items.length; i++) {
316 | let k = 'k' + items[i].store_id;
317 | //如果state里有该项数据,则忽略不覆盖
318 | if (undefined !== state.mutStoresState[k] && !cover) {
319 | continue;
320 | }
321 |
322 | let item = {
323 | // store_like_count: items[i].store_like_count,
324 | liked: items[i].liked || 0,
325 | };
326 | Vue.set(state.mutStoresState, k, item);
327 | }
328 | },
329 |
330 | /**
331 | * 帖子 的变化数据 记录到state
332 | */
333 | CHANGE_STORE(state, {
334 | mid,
335 | type
336 | }) {
337 | let item = state.mutThemesState['k' + mid];
338 | let update = {}
339 | switch(type) {
340 | case 'like':
341 | // update.theme_like_count = item.theme_like_count + 1
342 | update.liked = true
343 | break
344 | case 'unlike':
345 | // update.theme_like_count = item.theme_like_count - 1
346 | update.liked = false
347 | break
348 | }
349 |
350 | // Yes, Object.assign can update state and UI component at same time.
351 | if (!item) {
352 | let k = 'k' + mid;
353 | Vue.set(state.mutStoresState, k, update);
354 | } else {
355 | item = Object.assign(item, update)
356 | }
357 | },
358 |
359 | /**
360 | * 帖子 的变化数据 记录到state
361 | */
362 | ADD_GOODS_MUT(state, {
363 | items, cover=0
364 | }) {
365 | for(var i = 0; i < items.length; i++) {
366 | let k = 'k' + items[i].goods_id;
367 | //如果state里有该项数据,则忽略不覆盖
368 | if (undefined !== state.mutGoodsState[k] && !cover) {
369 | continue;
370 | }
371 |
372 | let item = {
373 | liked: items[i].liked || 0,
374 | };
375 | Vue.set(state.mutGoodsState, k, item);
376 | }
377 | },
378 |
379 | /**
380 | * 帖子 的变化数据 记录到state
381 | */
382 | CHANGE_GOODS(state, {
383 | mid,
384 | type,
385 | val
386 | }) {
387 | let item = state.mutGoodsState['k' + mid];
388 | let update = {}
389 | switch(type) {
390 | case 'like':
391 | // update.theme_like_count = item.theme_like_count + 1
392 | update.liked = true
393 | break
394 | case 'unlike':
395 | // update.theme_like_count = item.theme_like_count - 1
396 | update.liked = false
397 | break
398 | }
399 |
400 | // Yes, Object.assign can update state and UI component at same time.
401 | if (!item) {
402 | let k = 'k' + mid;
403 | Vue.set(state.mutGoodsState, k, update);
404 | } else {
405 | item = Object.assign(item, update)
406 | }
407 | },
408 | }
--------------------------------------------------------------------------------
/src/pages/store-index.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
23 |
24 |
25 |
37 |
38 |
39 |
40 |
41 | location_on 附近
42 |
45 |
46 |
47 |
71 |
72 |
73 |
74 | 精选餐厅
75 |
76 |
77 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
158 |
--------------------------------------------------------------------------------