Commit 1705091dba112b3e79c4e11ab669fa9b8c76f42b

Authored by wuxw
1 parent 10d3499d

开发完成 admin 台账功能

src/api/admin/orderManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取订单列表
  4 +export function listCorders(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/corders.listCorders',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve(res)
  14 + } else {
  15 + reject(new Error(res.msg || '获取订单列表失败'))
  16 + }
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
  22 +
  23 +// 获取应用列表
  24 +export function listPublicApps(params) {
  25 + return new Promise((resolve, reject) => {
  26 + request({
  27 + url: '/app.listPublicApps',
  28 + method: 'get',
  29 + params
  30 + }).then(response => {
  31 + const res = response.data
  32 + resolve(res)
  33 + }).catch(error => {
  34 + reject(error)
  35 + })
  36 + })
  37 +}
  38 +
  39 +// 获取订单日志
  40 +export function listUnitemLog(params) {
  41 + return new Promise((resolve, reject) => {
  42 + request({
  43 + url: '/corders.listUnitemLog',
  44 + method: 'get',
  45 + params
  46 + }).then(response => {
  47 + const res = response.data
  48 + if (res.code === 0) {
  49 + resolve(res)
  50 + } else {
  51 + reject(new Error(res.msg || '获取订单日志失败'))
  52 + }
  53 + }).catch(error => {
  54 + reject(error)
  55 + })
  56 + })
  57 +}
0 58 \ No newline at end of file
... ...
src/api/mall/housekeepingSjServApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询家政服务列表
  4 +export function queryHousekeepingServ(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/mall.getAdminMallOpenApi',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + total: res.total,
  16 + records: res.records
  17 + })
  18 + } else {
  19 + reject(new Error(res.msg || '查询家政服务列表失败'))
  20 + }
  21 + }).catch(error => {
  22 + reject(error)
  23 + })
  24 + })
  25 +}
  26 +
  27 +// 查询家政服务类型
  28 +export function queryHousekeepingType(params) {
  29 + return new Promise((resolve, reject) => {
  30 + request({
  31 + url: '/housekeepingType/queryHousekeepingType',
  32 + method: 'get',
  33 + params
  34 + }).then(response => {
  35 + const res = response.data
  36 + if (res.code === 0) {
  37 + resolve({
  38 + data: res.data
  39 + })
  40 + } else {
  41 + reject(new Error(res.msg || '查询家政服务类型失败'))
  42 + }
  43 + }).catch(error => {
  44 + reject(error)
  45 + })
  46 + })
  47 +}
0 48 \ No newline at end of file
... ...
src/api/mall/integralDetailApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取积分交易明细列表
  4 +export function getIntegralDetailList(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/mall.getAdminMallOpenApi',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + total: res.total
  16 + })
  17 + } else {
  18 + reject(new Error(res.msg || 'Failed to get points transaction details'))
  19 + }
  20 + }).catch(error => {
  21 + reject(error)
  22 + })
  23 + })
  24 +}
0 25 \ No newline at end of file
... ...
src/api/mall/productSjApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取商品列表
  4 +export function getAdminProductList(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/mall.getAdminMallOpenApi',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + total: res.total
  16 + })
  17 + } else {
  18 + reject(new Error(res.msg || 'Failed to get product list'))
  19 + }
  20 + }).catch(error => {
  21 + reject(error)
  22 + })
  23 + })
  24 +}
  25 +
  26 +// 删除商品
  27 +export function deleteProduct(data) {
  28 + return new Promise((resolve, reject) => {
  29 + request({
  30 + url: '/product/deleteProduct',
  31 + method: 'post',
  32 + data
  33 + }).then(response => {
  34 + const res = response.data
  35 + if (res.code === 0) {
  36 + resolve(res)
  37 + } else {
  38 + reject(new Error(res.msg || 'Failed to delete product'))
  39 + }
  40 + }).catch(error => {
  41 + reject(error)
  42 + })
  43 + })
  44 +}
0 45 \ No newline at end of file
... ...
src/api/mall/storeOrderCartManageApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询订单列表
  4 +export function queryAdminStoreOrderCart(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/mall.getAdminMallOpenApi',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + total: res.total
  16 + })
  17 + } else {
  18 + reject(new Error(res.msg || 'Failed to query order list'))
  19 + }
  20 + }).catch(error => {
  21 + reject(error)
  22 + })
  23 + })
  24 +}
  25 +
  26 +// 查询商铺列表
  27 +export function queryShopsByAdmin(params) {
  28 + return new Promise((resolve, reject) => {
  29 + request({
  30 + url: '/mall.getAdminMallOpenApi',
  31 + method: 'get',
  32 + params
  33 + }).then(response => {
  34 + const res = response.data
  35 + if (res.code === 0) {
  36 + resolve({
  37 + data: res.data,
  38 + total: res.total
  39 + })
  40 + } else {
  41 + reject(new Error(res.msg || 'Failed to query shops'))
  42 + }
  43 + }).catch(error => {
  44 + reject(error)
  45 + })
  46 + })
  47 +}
0 48 \ No newline at end of file
... ...
src/api/mall/storeOrderCartReturnApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 获取退货订单列表
  4 +export function getStoreOrderCartReturnList(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/mall.getAdminMallOpenApi',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + total: res.total
  16 + })
  17 + } else {
  18 + reject(new Error(res.msg || 'Failed to get store order cart return list'))
  19 + }
  20 + }).catch(error => {
  21 + reject(error)
  22 + })
  23 + })
  24 +}
0 25 \ No newline at end of file
... ...
src/api/mall/userIntegralApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询积分列表
  4 +export function queryIntegralList(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/mall.getAdminMallOpenApi',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve(res)
  14 + } else {
  15 + reject(new Error(res.msg || '查询积分列表失败'))
  16 + }
  17 + }).catch(error => {
  18 + reject(error)
  19 + })
  20 + })
  21 +}
0 22 \ No newline at end of file
... ...
src/api/user/userLoginApi.js 0 → 100644
  1 +import request from '@/utils/request'
  2 +
  3 +// 查询用户登录日志
  4 +export function queryUserLogin(params) {
  5 + return new Promise((resolve, reject) => {
  6 + request({
  7 + url: '/userLogin/queryUserLogin',
  8 + method: 'get',
  9 + params
  10 + }).then(response => {
  11 + const res = response.data
  12 + if (res.code === 0) {
  13 + resolve({
  14 + data: res.data,
  15 + records: res.records,
  16 + total: res.total
  17 + })
  18 + } else {
  19 + reject(new Error(res.msg || 'Failed to query user login logs'))
  20 + }
  21 + }).catch(error => {
  22 + reject(error)
  23 + })
  24 + })
  25 +}
  26 +
  27 +// 获取门店列表
  28 +export function listStores(params) {
  29 + return new Promise((resolve, reject) => {
  30 + request({
  31 + url: '/store.listStores',
  32 + method: 'get',
  33 + params
  34 + }).then(response => {
  35 + const res = response.data
  36 + if (res.code === 0) {
  37 + resolve({
  38 + data: res.data
  39 + })
  40 + } else {
  41 + reject(new Error(res.msg || 'Failed to get store list'))
  42 + }
  43 + }).catch(error => {
  44 + reject(error)
  45 + })
  46 + })
  47 +}
0 48 \ No newline at end of file
... ...
src/components/admin/viewUnItemLog.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('viewUnItemLog.title')"
  4 + :visible.sync="visible"
  5 + width="70%"
  6 + >
  7 + <el-form label-width="120px">
  8 + <el-form-item :label="$t('viewUnItemLog.serviceName')">
  9 + <el-input v-model="viewUnItemLogInfo.serviceName" disabled />
  10 + </el-form-item>
  11 + <el-row>
  12 + <el-col :span="12">
  13 + <el-form-item :label="$t('viewUnItemLog.action')">
  14 + <el-input v-model="viewUnItemLogInfo.action" disabled />
  15 + </el-form-item>
  16 + </el-col>
  17 + <el-col :span="12">
  18 + <el-form-item :label="$t('viewUnItemLog.actionObj')">
  19 + <el-input v-model="viewUnItemLogInfo.actionObj" disabled />
  20 + </el-form-item>
  21 + </el-col>
  22 + </el-row>
  23 + <el-form-item :label="$t('viewUnItemLog.preValue')">
  24 + <el-input
  25 + v-model="viewUnItemLogInfo.preValue"
  26 + type="textarea"
  27 + :rows="5"
  28 + disabled
  29 + />
  30 + </el-form-item>
  31 + <el-form-item :label="$t('viewUnItemLog.afterValue')">
  32 + <el-input
  33 + v-model="viewUnItemLogInfo.afterValue"
  34 + type="textarea"
  35 + :rows="5"
  36 + disabled
  37 + />
  38 + </el-form-item>
  39 + <el-form-item :label="$t('viewUnItemLog.logText')">
  40 + <el-input
  41 + v-model="viewUnItemLogInfo.logText"
  42 + type="textarea"
  43 + :rows="5"
  44 + disabled
  45 + />
  46 + </el-form-item>
  47 + </el-form>
  48 + <div slot="footer" class="dialog-footer">
  49 + <el-button type="warning" @click="visible = false">
  50 + {{ $t('common.cancel') }}
  51 + </el-button>
  52 + </div>
  53 + </el-dialog>
  54 +</template>
  55 +
  56 +<script>
  57 +import { listUnitemLog } from '@/api/admin/orderManageApi'
  58 +
  59 +export default {
  60 + name: 'ViewUnItemLog',
  61 + data() {
  62 + return {
  63 + visible: false,
  64 + viewUnItemLogInfo: {
  65 + bId: '',
  66 + serviceName: '',
  67 + logText: '',
  68 + preValue: '',
  69 + afterValue: '',
  70 + action: '',
  71 + actionObj: ''
  72 + }
  73 + }
  74 + },
  75 + methods: {
  76 + open(order) {
  77 + this.clearLog()
  78 + this.viewUnItemLogInfo.bId = order.bId
  79 +
  80 + if (order.action === 'ADD') {
  81 + this.viewUnItemLogInfo.action = this.$t('viewUnItemLog.add')
  82 + } else if (order.action === 'MOD') {
  83 + this.viewUnItemLogInfo.action = this.$t('viewUnItemLog.modify')
  84 + } else if (order.action === 'DEL') {
  85 + this.viewUnItemLogInfo.action = this.$t('viewUnItemLog.delete')
  86 + } else {
  87 + this.viewUnItemLogInfo.action = '-'
  88 + }
  89 +
  90 + this.viewUnItemLogInfo.actionObj = order.actionObj
  91 + this.visible = true
  92 + this._loadOrderUnitemLog()
  93 + },
  94 + async _loadOrderUnitemLog() {
  95 + try {
  96 + const res = await listUnitemLog({ bId: this.viewUnItemLogInfo.bId })
  97 + Object.assign(this.viewUnItemLogInfo, res.data)
  98 +
  99 + const logText = JSON.parse(res.data.logText)
  100 + this.viewUnItemLogInfo.preValue = JSON.stringify(logText.preValue, null, 2)
  101 + this.viewUnItemLogInfo.afterValue = JSON.stringify(logText.afterValue, null, 2)
  102 + } catch (error) {
  103 + this.$message.error(this.$t('viewUnItemLog.fetchError'))
  104 + }
  105 + },
  106 + clearLog() {
  107 + this.viewUnItemLogInfo = {
  108 + bId: '',
  109 + serviceName: '',
  110 + logText: '',
  111 + preValue: '',
  112 + afterValue: '',
  113 + action: '',
  114 + actionObj: ''
  115 + }
  116 + }
  117 + }
  118 +}
  119 +</script>
0 120 \ No newline at end of file
... ...
src/components/mall/DeleteProduct.vue 0 → 100644
  1 +<template>
  2 + <el-dialog
  3 + :title="$t('deleteProduct.title')"
  4 + :visible.sync="visible"
  5 + width="30%"
  6 + :before-close="handleClose"
  7 + >
  8 + <div style="text-align: center;">
  9 + <p>{{ $t('deleteProduct.confirm') }}</p>
  10 + </div>
  11 + <span slot="footer" class="dialog-footer">
  12 + <el-button @click="handleClose">{{ $t('deleteProduct.cancel') }}</el-button>
  13 + <el-button type="primary" @click="confirmDelete">{{ $t('deleteProduct.confirmBtn') }}</el-button>
  14 + </span>
  15 + </el-dialog>
  16 +</template>
  17 +
  18 +<script>
  19 +import { deleteProduct } from '@/api/mall/productSjApi'
  20 +
  21 +export default {
  22 + name: 'DeleteProduct',
  23 + data() {
  24 + return {
  25 + visible: false,
  26 + productId: ''
  27 + }
  28 + },
  29 + methods: {
  30 + open(productId) {
  31 + this.productId = productId
  32 + this.visible = true
  33 + },
  34 + handleClose() {
  35 + this.visible = false
  36 + },
  37 + async confirmDelete() {
  38 + try {
  39 + await deleteProduct({ productId: this.productId })
  40 + this.$message.success(this.$t('deleteProduct.success'))
  41 + this.$emit('success')
  42 + this.handleClose()
  43 + } catch (error) {
  44 + this.$message.error(this.$t('deleteProduct.error'))
  45 + }
  46 + }
  47 + }
  48 +}
  49 +</script>
0 50 \ No newline at end of file
... ...
src/components/mall/DeleteProductLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + deleteProduct: {
  4 + title: 'Please confirm your operation',
  5 + confirm: 'Are you sure to delete this product?',
  6 + cancel: 'Cancel',
  7 + confirmBtn: 'Confirm Delete',
  8 + success: 'Product deleted successfully',
  9 + error: 'Failed to delete product'
  10 + }
  11 + },
  12 + zh: {
  13 + deleteProduct: {
  14 + title: '请确认您的操作',
  15 + confirm: '确定删除该商品吗?',
  16 + cancel: '点错了',
  17 + confirmBtn: '确认删除',
  18 + success: '商品删除成功',
  19 + error: '删除商品失败'
  20 + }
  21 + }
  22 +}
0 23 \ No newline at end of file
... ...
src/components/mall/Pagination.vue 0 → 100644
  1 +<template>
  2 + <el-pagination
  3 + :current-page.sync="currentPage"
  4 + :page-sizes="[10, 20, 30, 50]"
  5 + :page-size="pageSize"
  6 + :total="total"
  7 + layout="total, sizes, prev, pager, next, jumper"
  8 + @size-change="handleSizeChange"
  9 + @current-change="handleCurrentChange"
  10 + />
  11 +</template>
  12 +
  13 +<script>
  14 +export default {
  15 + name: 'Pagination',
  16 + props: {
  17 + currentPage: {
  18 + type: Number,
  19 + default: 1
  20 + },
  21 + pageSize: {
  22 + type: Number,
  23 + default: 10
  24 + },
  25 + total: {
  26 + type: Number,
  27 + default: 0
  28 + }
  29 + },
  30 + methods: {
  31 + handleSizeChange(val) {
  32 + this.$emit('size-change', val)
  33 + },
  34 + handleCurrentChange(val) {
  35 + this.$emit('current-change', val)
  36 + }
  37 + }
  38 +}
  39 +</script>
0 40 \ No newline at end of file
... ...
src/components/user/Pagination.vue 0 → 100644
  1 +<template>
  2 + <el-pagination
  3 + @size-change="handleSizeChange"
  4 + @current-change="handleCurrentChange"
  5 + :current-page="currentPage"
  6 + :page-sizes="[10, 20, 30, 50]"
  7 + :page-size="pageSize"
  8 + layout="total, sizes, prev, pager, next, jumper"
  9 + :total="total">
  10 + </el-pagination>
  11 +</template>
  12 +
  13 +<script>
  14 +export default {
  15 + name: 'Pagination',
  16 + props: {
  17 + currentPage: {
  18 + type: Number,
  19 + default: 1
  20 + },
  21 + pageSize: {
  22 + type: Number,
  23 + default: 10
  24 + },
  25 + total: {
  26 + type: Number,
  27 + default: 0
  28 + }
  29 + },
  30 + methods: {
  31 + handleSizeChange(val) {
  32 + this.$emit('size-change', val)
  33 + },
  34 + handleCurrentChange(val) {
  35 + this.$emit('current-change', val)
  36 + }
  37 + }
  38 +}
  39 +</script>
0 40 \ No newline at end of file
... ...
src/i18n/index.js
... ... @@ -88,6 +88,14 @@ import { messages as operationalAnalysisMessages } from &#39;../views/report/operati
88 88 import { messages as communityFeeSummaryMessages } from '../views/report/communityFeeSummaryLang'
89 89 import { messages as adminPayFeeDetailMessages } from '../views/fee/adminPayFeeDetailLang'
90 90 import { messages as adminOweFeeDetailMessages } from '../views/fee/adminOweFeeDetailLang'
  91 +import { messages as orderManageMessages } from '../views/admin/orderManageLang'
  92 +import { messages as userLoginMessages } from '../views/user/userLoginLang'
  93 +import { messages as productSjMessages } from '../views/mall/productSjLang'
  94 +import { messages as housekeepingSjServMessages } from '../views/mall/housekeepingSjServLang'
  95 +import { messages as storeOrderCartManageMessages } from '../views/mall/storeOrderCartManageLang'
  96 +import { messages as storeOrderCartReturnMessages } from '../views/mall/storeOrderCartReturnLang'
  97 +import { messages as userIntegralMessages } from '../views/mall/userIntegralLang'
  98 +import { messages as integralDetailMessages } from '../views/mall/integralDetailLang'
91 99  
92 100 Vue.use(VueI18n)
93 101  
... ... @@ -180,6 +188,14 @@ const messages = {
180 188 ...communityFeeSummaryMessages.en,
181 189 ...adminPayFeeDetailMessages.en,
182 190 ...adminOweFeeDetailMessages.en,
  191 + ...orderManageMessages.en,
  192 + ...userLoginMessages.en,
  193 + ...productSjMessages.en,
  194 + ...housekeepingSjServMessages.en,
  195 + ...storeOrderCartManageMessages.en,
  196 + ...storeOrderCartReturnMessages.en,
  197 + ...userIntegralMessages.en,
  198 + ...integralDetailMessages.en,
183 199 },
184 200 zh: {
185 201 ...loginMessages.zh,
... ... @@ -268,6 +284,14 @@ const messages = {
268 284 ...communityFeeSummaryMessages.zh,
269 285 ...adminPayFeeDetailMessages.zh,
270 286 ...adminOweFeeDetailMessages.zh,
  287 + ...orderManageMessages.zh,
  288 + ...userLoginMessages.zh,
  289 + ...productSjMessages.zh,
  290 + ...housekeepingSjServMessages.zh,
  291 + ...storeOrderCartManageMessages.zh,
  292 + ...storeOrderCartReturnMessages.zh,
  293 + ...userIntegralMessages.zh,
  294 + ...integralDetailMessages.zh,
271 295 }
272 296 }
273 297  
... ...
src/router/index.js
... ... @@ -426,6 +426,46 @@ const routes = [
426 426 name: '/pages/fee/adminOweFeeDetail',
427 427 component: () => import('@/views/fee/adminOweFeeDetailList.vue')
428 428 },
  429 + {
  430 + path: '/pages/admin/orderManage',
  431 + name: '/pages/admin/orderManage',
  432 + component: () => import('@/views/admin/orderManageList.vue')
  433 + },
  434 + {
  435 + path: '/pages/frame/userLogin',
  436 + name: '/pages/frame/userLogin',
  437 + component: () => import('@/views/user/userLoginList.vue')
  438 + },
  439 + {
  440 + path: '/pages/admin/productSj',
  441 + name: '/pages/admin/productSj',
  442 + component: () => import('@/views/mall/productSjList.vue')
  443 + },
  444 + {
  445 + path: '/pages/admin/housekeepingSjServ',
  446 + name: '/pages/admin/housekeepingSjServ',
  447 + component: () => import('@/views/mall/housekeepingSjServList.vue')
  448 + },
  449 + {
  450 + path: '/pages/admin/storeOrderCartManage',
  451 + name: '/pages/admin/storeOrderCartManage',
  452 + component: () => import('@/views/mall/storeOrderCartManageList.vue')
  453 + },
  454 + {
  455 + path: '/pages/admin/storeOrderCartReturn',
  456 + name: '/pages/admin/storeOrderCartReturn',
  457 + component: () => import('@/views/mall/storeOrderCartReturnList.vue')
  458 + },
  459 + {
  460 + path: '/pages/admin/userIntegral',
  461 + name: '/pages/admin/userIntegral',
  462 + component: () => import('@/views/mall/userIntegralList.vue')
  463 + },
  464 + {
  465 + path: '/pages/admin/integralDetail',
  466 + name: '/pages/admin/integralDetail',
  467 + component: () => import('@/views/mall/integralDetailList.vue')
  468 + },
429 469 // 其他子路由可以在这里添加
430 470 ]
431 471 },
... ...
src/views/admin/orderManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + orderManage: {
  4 + queryCondition: 'Query Condition',
  5 + orderList: 'Order List',
  6 + orderId: 'Order ID',
  7 + externalId: 'External ID',
  8 + businessId: 'Business ID',
  9 + startTime: 'Start Time',
  10 + endTime: 'End Time',
  11 + operator: 'Operator',
  12 + businessName: 'Business Name',
  13 + appName: 'App Name',
  14 + createTime: 'Create Time',
  15 + action: 'Action',
  16 + actionObj: 'Action Object',
  17 + status: 'Status',
  18 + operation: 'Operation',
  19 + log: 'Log',
  20 + noLog: 'No Log',
  21 + add: 'Add',
  22 + modify: 'Modify',
  23 + delete: 'Delete',
  24 + completed: 'Completed',
  25 + failed: 'Failed',
  26 + allApps: 'All Apps',
  27 + fetchError: 'Failed to fetch orders',
  28 + fetchAppsError: 'Failed to fetch apps'
  29 + },
  30 + viewUnItemLog: {
  31 + title: 'Order Log',
  32 + serviceName: 'Service Name',
  33 + action: 'Action',
  34 + actionObj: 'Action Object',
  35 + preValue: 'Before Value',
  36 + afterValue: 'After Value',
  37 + logText: 'Original Log',
  38 + add: 'Add',
  39 + modify: 'Modify',
  40 + delete: 'Delete',
  41 + fetchError: 'Failed to fetch log'
  42 + }
  43 + },
  44 + zh: {
  45 + orderManage: {
  46 + queryCondition: '查询条件',
  47 + orderList: '受理单',
  48 + orderId: '订单编号',
  49 + externalId: '外部编号',
  50 + businessId: '业务编号',
  51 + startTime: '受理开始时间',
  52 + endTime: '受理结束时间',
  53 + operator: '操作人',
  54 + businessName: '业务名称',
  55 + appName: '应用名称',
  56 + createTime: '受理时间',
  57 + action: '受理动作',
  58 + actionObj: '受理表',
  59 + status: '状态',
  60 + operation: '操作',
  61 + log: '日志',
  62 + noLog: '无日志',
  63 + add: '添加',
  64 + modify: '修改',
  65 + delete: '删除',
  66 + completed: '完成',
  67 + failed: '失败',
  68 + allApps: '全部应用',
  69 + fetchError: '获取订单列表失败',
  70 + fetchAppsError: '获取应用列表失败'
  71 + },
  72 + viewUnItemLog: {
  73 + title: '受理记录',
  74 + serviceName: '受理服务',
  75 + action: '受理动作',
  76 + actionObj: '受理表',
  77 + preValue: '受理前',
  78 + afterValue: '受理后',
  79 + logText: '原始记录',
  80 + add: '添加',
  81 + modify: '修改',
  82 + delete: '删除',
  83 + fetchError: '获取日志失败'
  84 + }
  85 + }
  86 +}
0 87 \ No newline at end of file
... ...
src/views/admin/orderManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="order-manage-container animated fadeInRight">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4">
  5 + <el-card class="border-radius">
  6 + <div class="treeview attendance-staff">
  7 + <ul class="list-group text-center border-radius">
  8 + <li v-for="(item, index) in orderManageInfo.apps" :key="index" class="list-group-item node-orgTree"
  9 + :class="{ 'vc-node-selected': orderManageInfo.conditions.appId == item.appId }" @click="swatchApp(item)">
  10 + {{ item.name }}
  11 + </li>
  12 + </ul>
  13 + </div>
  14 + </el-card>
  15 + </el-col>
  16 + <el-col :span="20">
  17 + <el-card>
  18 + <div slot="header" class="text-left">
  19 + <span>{{ $t('orderManage.queryCondition') }}</span>
  20 + </div>
  21 + <el-row :gutter="20">
  22 + <el-col :span="4">
  23 + <el-input v-model="orderManageInfo.conditions.oId" :placeholder="$t('orderManage.orderId')" clearable />
  24 + </el-col>
  25 + <el-col :span="4">
  26 + <el-input v-model="orderManageInfo.conditions.extTransactionId" :placeholder="$t('orderManage.externalId')"
  27 + clearable />
  28 + </el-col>
  29 + <el-col :span="4">
  30 + <el-input v-model="orderManageInfo.conditions.bId" :placeholder="$t('orderManage.businessId')" clearable />
  31 + </el-col>
  32 + <el-col :span="4">
  33 + <el-date-picker v-model="orderManageInfo.conditions.startTime" type="datetime"
  34 + :placeholder="$t('orderManage.startTime')" class="w-100" />
  35 + </el-col>
  36 + <el-col :span="4">
  37 + <el-date-picker v-model="orderManageInfo.conditions.endTime" type="datetime"
  38 + :placeholder="$t('orderManage.endTime')" class="w-100" />
  39 + </el-col>
  40 + <el-col :span="4">
  41 + <el-button type="primary" @click="_queryOrdersMethod">
  42 + <i class="el-icon-search"></i>
  43 + {{ $t('common.search') }}
  44 + </el-button>
  45 + </el-col>
  46 + </el-row>
  47 + <el-row :gutter="20" class="mt-10">
  48 + <el-col :span="4">
  49 + <el-input v-model="orderManageInfo.conditions.staffNameLike" :placeholder="$t('orderManage.operator')"
  50 + clearable />
  51 + </el-col>
  52 + <el-col :span="4">
  53 + <el-input v-model="orderManageInfo.conditions.businessTypeNameLike"
  54 + :placeholder="$t('orderManage.businessName')" clearable />
  55 + </el-col>
  56 + </el-row>
  57 + </el-card>
  58 +
  59 + <el-card class="mt-20">
  60 + <div slot="header" class="text-left">
  61 + <span>{{ $t('orderManage.orderList') }}</span>
  62 + </div>
  63 + <el-table :data="orderManageInfo.orderDataVos" border style="width: 100%">
  64 + <el-table-column prop="appName" :label="$t('orderManage.appName')" align="center" />
  65 + <el-table-column :label="$t('orderManage.orderId')" align="center">
  66 + <template slot-scope="scope">
  67 + <div>{{ scope.row.oId }}</div>
  68 + <div>({{ scope.row.extTransactionId }})</div>
  69 + </template>
  70 + </el-table-column>
  71 + <el-table-column :label="$t('orderManage.businessName')" align="center">
  72 + <template slot-scope="scope">
  73 + <div>{{ scope.row.name }}</div>
  74 + <div>({{ scope.row.businessTypeCd }})</div>
  75 + </template>
  76 + </el-table-column>
  77 + <el-table-column prop="bId" :label="$t('orderManage.businessId')" align="center" />
  78 + <el-table-column prop="createTime" :label="$t('orderManage.createTime')" align="center" />
  79 + <el-table-column :label="$t('orderManage.action')" align="center">
  80 + <template slot-scope="scope">
  81 + <span v-if="scope.row.action == 'ADD'">{{ $t('orderManage.add') }}</span>
  82 + <span v-else-if="scope.row.action == 'MOD'">{{ $t('orderManage.modify') }}</span>
  83 + <span v-else-if="scope.row.action == 'DEL'">{{ $t('orderManage.delete') }}</span>
  84 + <span v-else>-</span>
  85 + </template>
  86 + </el-table-column>
  87 + <el-table-column prop="actionObj" :label="$t('orderManage.actionObj')" align="center" />
  88 + <el-table-column prop="userName" :label="$t('orderManage.operator')" align="center" />
  89 + <el-table-column :label="$t('orderManage.status')" align="center">
  90 + <template slot-scope="scope">
  91 + {{ scope.row.statusCd == 'C' ? $t('orderManage.completed') : $t('orderManage.failed') }}
  92 + </template>
  93 + </el-table-column>
  94 + <el-table-column :label="$t('common.operation')" align="center">
  95 + <template slot-scope="scope">
  96 + <el-button v-if="scope.row.bId" size="mini" @click="_showUnitemLog(scope.row)">
  97 + {{ $t('orderManage.log') }}
  98 + </el-button>
  99 + <span v-else>{{ $t('orderManage.noLog') }}</span>
  100 + </template>
  101 + </el-table-column>
  102 + </el-table>
  103 + <el-pagination :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  104 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  105 + @current-change="handleCurrentChange" />
  106 + </el-card>
  107 + </el-col>
  108 + </el-row>
  109 +
  110 + <view-un-item-log ref="viewUnItemLog" />
  111 + </div>
  112 +</template>
  113 +
  114 +<script>
  115 +import { listCorders, listPublicApps } from '@/api/admin/orderManageApi'
  116 +import ViewUnItemLog from '@/components/admin/viewUnItemLog'
  117 +
  118 +export default {
  119 + name: 'OrderManageList',
  120 + components: {
  121 + ViewUnItemLog
  122 + },
  123 + data() {
  124 + return {
  125 + orderManageInfo: {
  126 + orderDataVos: [],
  127 + apps: [],
  128 + total: 0,
  129 + records: 1,
  130 + conditions: {
  131 + oId: '',
  132 + extTransactionId: '',
  133 + orderTypeCd: '',
  134 + appId: '',
  135 + startTime: '',
  136 + endTime: '',
  137 + staffNameLike: '',
  138 + bId: '',
  139 + businessTypeNameLike: '',
  140 + page: 1,
  141 + row: 20
  142 + }
  143 + },
  144 + page: {
  145 + current: 1,
  146 + size: 20,
  147 + total: 0
  148 + }
  149 + }
  150 + },
  151 + created() {
  152 + this._listOrders(this.page.current, this.page.size)
  153 + this._loadApps()
  154 + },
  155 + methods: {
  156 + async _listOrders(page, rows) {
  157 + try {
  158 + this.orderManageInfo.conditions.page = page
  159 + this.orderManageInfo.conditions.row = rows
  160 + const params = { ...this.orderManageInfo.conditions }
  161 +
  162 + const res = await listCorders(params)
  163 + this.orderManageInfo.total = res.total
  164 + this.orderManageInfo.records = res.records
  165 + this.orderManageInfo.orderDataVos = res.data
  166 + this.page.total = res.records
  167 + } catch (error) {
  168 + this.$message.error(this.$t('orderManage.fetchError'))
  169 + }
  170 + },
  171 + async _loadApps() {
  172 + try {
  173 + this.orderManageInfo.apps = [{
  174 + appId: '',
  175 + name: this.$t('orderManage.allApps')
  176 + }]
  177 +
  178 + const res = await listPublicApps({ page: 1, row: 50 })
  179 + this.orderManageInfo.apps = [...this.orderManageInfo.apps, ...res.apps]
  180 + } catch (error) {
  181 + this.$message.error(this.$t('orderManage.fetchAppsError'))
  182 + }
  183 + },
  184 + _queryOrdersMethod() {
  185 + this.page.current = 1
  186 + this._listOrders(this.page.current, this.page.size)
  187 + },
  188 + swatchApp(app) {
  189 + this.orderManageInfo.conditions.appId = app.appId
  190 + this._listOrders(this.page.current, this.page.size)
  191 + },
  192 + _showUnitemLog(order) {
  193 + this.$refs.viewUnItemLog.open(order)
  194 + },
  195 + handleSizeChange(val) {
  196 + this.page.size = val
  197 + this._listOrders(this.page.current, this.page.size)
  198 + },
  199 + handleCurrentChange(val) {
  200 + this.page.current = val
  201 + this._listOrders(this.page.current, this.page.size)
  202 + }
  203 + }
  204 +}
  205 +</script>
  206 +
  207 +<style scoped>
  208 +.order-manage-container {
  209 + padding: 20px;
  210 +}
  211 +
  212 +.border-radius {
  213 + border-radius: 4px;
  214 +}
  215 +
  216 +.list-group {
  217 + list-style: none;
  218 + padding: 0;
  219 + margin: 0;
  220 +}
  221 +
  222 +.list-group-item {
  223 + padding: 10px;
  224 + cursor: pointer;
  225 +}
  226 +
  227 +.list-group-item:hover {
  228 + background-color: #f5f7fa;
  229 +}
  230 +
  231 +.vc-node-selected {
  232 + background-color: #ecf5ff;
  233 + color: #409eff;
  234 +}
  235 +
  236 +.mt-10 {
  237 + margin-top: 10px;
  238 +}
  239 +
  240 +.mt-20 {
  241 + margin-top: 20px;
  242 +}
  243 +
  244 +.w-100 {
  245 + width: 100%;
  246 +}
  247 +</style>
0 248 \ No newline at end of file
... ...
src/views/mall/housekeepingSjServLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + housekeepingSjServ: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + servName: 'Please enter service name',
  7 + hktId: 'Please select service type'
  8 + },
  9 + list: {
  10 + title: 'On Shelf Services',
  11 + today: 'Today On Shelf',
  12 + all: 'All On Shelf'
  13 + },
  14 + table: {
  15 + servId: 'Service ID',
  16 + servName: 'Service Name',
  17 + servDesc: 'Service Description',
  18 + hktName: 'Service Type',
  19 + repairWay: 'Dispatch Method',
  20 + returnVisitFlag: 'Return Visit Method',
  21 + sales: 'Sales',
  22 + defaultFee: 'Default Fee',
  23 + sort: 'Sort',
  24 + state: 'Shelf Status'
  25 + },
  26 + repairWay: {
  27 + grab: 'Grab Order',
  28 + assign: 'Assign',
  29 + roundRobin: 'Round Robin'
  30 + },
  31 + returnVisit: {
  32 + none: 'No Return Visit',
  33 + ratedNoVisit: 'No Visit After Rated',
  34 + allVisit: 'All Return Visit'
  35 + },
  36 + state: {
  37 + notOnShelf: 'Not On Shelf',
  38 + onShelf: 'On Shelf'
  39 + },
  40 + fetchError: 'Failed to fetch service list',
  41 + fetchTypeError: 'Failed to fetch service types'
  42 + }
  43 + },
  44 + zh: {
  45 + housekeepingSjServ: {
  46 + search: {
  47 + title: '查询条件',
  48 + servName: '请输入服务名称',
  49 + hktId: '请选择服务类型'
  50 + },
  51 + list: {
  52 + title: '上架服务',
  53 + today: '今日上架',
  54 + all: '所有上架'
  55 + },
  56 + table: {
  57 + servId: '服务编号',
  58 + servName: '服务名称',
  59 + servDesc: '服务描述',
  60 + hktName: '服务类型',
  61 + repairWay: '派单方式',
  62 + returnVisitFlag: '回访方式',
  63 + sales: '销量',
  64 + defaultFee: '默认费用',
  65 + sort: '排序',
  66 + state: '上架状态'
  67 + },
  68 + repairWay: {
  69 + grab: '抢单',
  70 + assign: '指派',
  71 + roundRobin: '轮训'
  72 + },
  73 + returnVisit: {
  74 + none: '都不回访',
  75 + ratedNoVisit: '已评价不回访',
  76 + allVisit: '都回访'
  77 + },
  78 + state: {
  79 + notOnShelf: '未上架',
  80 + onShelf: '上架'
  81 + },
  82 + fetchError: '获取服务列表失败',
  83 + fetchTypeError: '获取服务类型失败'
  84 + }
  85 + }
  86 +}
0 87 \ No newline at end of file
... ...
src/views/mall/housekeepingSjServList.vue 0 → 100644
  1 +<template>
  2 + <div class="housekeeping-sj-serv-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="clearfix text-left">
  6 + <span>{{ $t('housekeepingSjServ.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input v-model="searchForm.servName" :placeholder="$t('housekeepingSjServ.search.servName')" clearable
  11 + @keyup.enter.native="handleSearch" />
  12 + </el-col>
  13 + <el-col :span="6">
  14 + <el-select v-model="searchForm.hktId" :placeholder="$t('housekeepingSjServ.search.hktId')" clearable>
  15 + <el-option v-for="item in housekeepingTypes" :key="item.hktId" :label="item.hktName" :value="item.hktId" />
  16 + </el-select>
  17 + </el-col>
  18 + <el-col :span="4">
  19 + <el-button type="primary" @click="handleSearch">
  20 + <i class="el-icon-search"></i>
  21 + {{ $t('common.search') }}
  22 + </el-button>
  23 + </el-col>
  24 + </el-row>
  25 + </el-card>
  26 +
  27 + <!-- 上架服务列表 -->
  28 + <el-card class="list-wrapper">
  29 + <div slot="header" class="clearfix text-left">
  30 + <span>{{ $t('housekeepingSjServ.list.title') }}</span>
  31 + <div style="float: right;">
  32 + <el-button type="primary" size="small" @click="listHousekeepingServsToDay">
  33 + <i class="el-icon-plus"></i>
  34 + {{ $t('housekeepingSjServ.list.today') }}
  35 + </el-button>
  36 + <el-button type="primary" size="small" style="margin-left: 10px" @click="listHousekeepingServsAll">
  37 + {{ $t('housekeepingSjServ.list.all') }}
  38 + </el-button>
  39 + </div>
  40 + </div>
  41 +
  42 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  43 + <el-table-column prop="servId" :label="$t('housekeepingSjServ.table.servId')" align="center" />
  44 + <el-table-column prop="servName" :label="$t('housekeepingSjServ.table.servName')" align="center" />
  45 + <el-table-column prop="servDesc" :label="$t('housekeepingSjServ.table.servDesc')" align="center" />
  46 + <el-table-column prop="hktName" :label="$t('housekeepingSjServ.table.hktName')" align="center" />
  47 + <el-table-column :label="$t('housekeepingSjServ.table.repairWay')" align="center">
  48 + <template slot-scope="scope">
  49 + <span v-if="scope.row.repairWay === '100'">{{ $t('housekeepingSjServ.repairWay.grab') }}</span>
  50 + <span v-else-if="scope.row.repairWay === '200'">{{ $t('housekeepingSjServ.repairWay.assign') }}</span>
  51 + <span v-else-if="scope.row.repairWay === '300'">{{ $t('housekeepingSjServ.repairWay.roundRobin') }}</span>
  52 + </template>
  53 + </el-table-column>
  54 + <el-table-column :label="$t('housekeepingSjServ.table.returnVisitFlag')" align="center">
  55 + <template slot-scope="scope">
  56 + <span v-if="scope.row.returnVisitFlag === '001'">{{ $t('housekeepingSjServ.returnVisit.none') }}</span>
  57 + <span v-else-if="scope.row.returnVisitFlag === '002'">{{ $t('housekeepingSjServ.returnVisit.ratedNoVisit')
  58 + }}</span>
  59 + <span v-else-if="scope.row.returnVisitFlag === '003'">{{ $t('housekeepingSjServ.returnVisit.allVisit')
  60 + }}</span>
  61 + </template>
  62 + </el-table-column>
  63 + <el-table-column prop="sales" :label="$t('housekeepingSjServ.table.sales')" align="center" />
  64 + <el-table-column prop="defaultFee" :label="$t('housekeepingSjServ.table.defaultFee')" align="center" />
  65 + <el-table-column prop="sort" :label="$t('housekeepingSjServ.table.sort')" align="center" />
  66 + <el-table-column :label="$t('housekeepingSjServ.table.state')" align="center">
  67 + <template slot-scope="scope">
  68 + {{ scope.row.state === '1001' ? $t('housekeepingSjServ.state.notOnShelf') :
  69 + $t('housekeepingSjServ.state.onShelf') }}
  70 + </template>
  71 + </el-table-column>
  72 + </el-table>
  73 +
  74 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  75 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  76 + @current-change="handleCurrentChange" />
  77 + </el-card>
  78 + </div>
  79 +</template>
  80 +
  81 +<script>
  82 +import { queryHousekeepingServ, queryHousekeepingType } from '@/api/mall/housekeepingSjServApi'
  83 +
  84 +export default {
  85 + name: 'HousekeepingSjServList',
  86 + data() {
  87 + return {
  88 + loading: false,
  89 + searchForm: {
  90 + servName: '',
  91 + hktId: '',
  92 + state: '2002',
  93 + createTime: '',
  94 + mallApiCode: 'queryHousekeepingServBmoImpl'
  95 + },
  96 + tableData: [],
  97 + housekeepingTypes: [],
  98 + page: {
  99 + current: 1,
  100 + size: 10,
  101 + total: 0
  102 + }
  103 + }
  104 + },
  105 + created() {
  106 + this.getList()
  107 + this.getHousekeepingTypes()
  108 + },
  109 + methods: {
  110 + async getList() {
  111 + try {
  112 + this.loading = true
  113 + const params = {
  114 + page: this.page.current,
  115 + row: this.page.size,
  116 + ...this.searchForm
  117 + }
  118 + const { data, total } = await queryHousekeepingServ(params)
  119 + this.tableData = data
  120 + this.page.total = total
  121 + } catch (error) {
  122 + this.$message.error(this.$t('housekeepingSjServ.fetchError'))
  123 + } finally {
  124 + this.loading = false
  125 + }
  126 + },
  127 + async getHousekeepingTypes() {
  128 + try {
  129 + const params = {
  130 + page: 1,
  131 + row: 50,
  132 + typeCd: 1001,
  133 + shopId: ''
  134 + }
  135 + const { data } = await queryHousekeepingType(params)
  136 + this.housekeepingTypes = data
  137 + } catch (error) {
  138 + this.$message.error(this.$t('housekeepingSjServ.fetchTypeError'))
  139 + }
  140 + },
  141 + handleSearch() {
  142 + this.page.current = 1
  143 + this.getList()
  144 + },
  145 + listHousekeepingServsToDay() {
  146 + this.searchForm.createTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss')
  147 + this.handleSearch()
  148 + },
  149 + listHousekeepingServsAll() {
  150 + this.searchForm.createTime = ''
  151 + this.handleSearch()
  152 + },
  153 + handleSizeChange(val) {
  154 + this.page.size = val
  155 + this.getList()
  156 + },
  157 + handleCurrentChange(val) {
  158 + this.page.current = val
  159 + this.getList()
  160 + }
  161 + }
  162 +}
  163 +</script>
  164 +
  165 +<style lang="scss" scoped>
  166 +.housekeeping-sj-serv-container {
  167 + padding: 20px;
  168 +
  169 + .search-wrapper {
  170 + margin-bottom: 20px;
  171 +
  172 + .el-select {
  173 + width: 100%;
  174 + }
  175 + }
  176 +
  177 + .list-wrapper {
  178 + .el-pagination {
  179 + margin-top: 20px;
  180 + text-align: right;
  181 + }
  182 + }
  183 +}
  184 +</style>
0 185 \ No newline at end of file
... ...
src/views/mall/integralDetailLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + integralDetail: {
  4 + all: 'All',
  5 + personal: 'Personal',
  6 + merchant: 'Merchant',
  7 + searchTitle: 'Search Conditions',
  8 + accountPlaceholder: 'Please enter account',
  9 + typePlaceholder: 'Please select type',
  10 + objectTypePlaceholder: 'Please select object type',
  11 + orderIdPlaceholder: 'Please enter order ID',
  12 + transferIn: 'Transfer In',
  13 + transferOut: 'Transfer Out',
  14 + user: 'User',
  15 + tableTitle: 'Points Transaction',
  16 + id: 'ID',
  17 + accountName: 'Account Name',
  18 + accountId: 'Account ID',
  19 + type: 'Type',
  20 + relatedAccount: 'Related Account',
  21 + points: 'Points',
  22 + objectType: 'Object Type',
  23 + objectId: 'Object ID',
  24 + phone: 'Phone',
  25 + orderId: 'Order ID',
  26 + transactionTime: 'Transaction Time',
  27 + remark: 'Remark',
  28 + fetchError: 'Failed to fetch points transaction data'
  29 + }
  30 + },
  31 + zh: {
  32 + integralDetail: {
  33 + all: '全部',
  34 + personal: '个人',
  35 + merchant: '商户',
  36 + searchTitle: '查询条件',
  37 + accountPlaceholder: '请填写账户',
  38 + typePlaceholder: '请选择类型',
  39 + objectTypePlaceholder: '请选择对象类型',
  40 + orderIdPlaceholder: '请选择交易单号',
  41 + transferIn: '转入',
  42 + transferOut: '转出',
  43 + user: '用户',
  44 + tableTitle: '积分交易',
  45 + id: '编号',
  46 + accountName: '账户名称',
  47 + accountId: '账户编号',
  48 + type: '类型',
  49 + relatedAccount: '关联账户',
  50 + points: '积分数',
  51 + objectType: '对象类型',
  52 + objectId: '对象ID',
  53 + phone: '手机号',
  54 + orderId: '交易单号',
  55 + transactionTime: '交易时间',
  56 + remark: '备注',
  57 + fetchError: '获取积分交易数据失败'
  58 + }
  59 + }
  60 +}
0 61 \ No newline at end of file
... ...
src/views/mall/integralDetailList.vue 0 → 100644
  1 +<template>
  2 + <div class="integral-detail-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="3">
  5 + <el-card class="tree-card">
  6 + <ul class="tree-list">
  7 + <li class="tree-item" @click="_switchIntegralObjType('')"
  8 + :class="{ 'active': integralDetailInfo.conditions.objType === '' }">
  9 + {{ $t('integralDetail.all') }}
  10 + </li>
  11 + <li class="tree-item" @click="_switchIntegralObjType('6006')"
  12 + :class="{ 'active': integralDetailInfo.conditions.objType === '6006' }">
  13 + {{ $t('integralDetail.personal') }}
  14 + </li>
  15 + <li class="tree-item" @click="_switchIntegralObjType('7007')"
  16 + :class="{ 'active': integralDetailInfo.conditions.objType === '7007' }">
  17 + {{ $t('integralDetail.merchant') }}
  18 + </li>
  19 + </ul>
  20 + </el-card>
  21 + </el-col>
  22 + <el-col :span="21">
  23 + <el-card class="search-card">
  24 + <div slot="header" class="clearfix text-left">
  25 + <span>{{ $t('integralDetail.searchTitle') }}</span>
  26 + </div>
  27 + <el-form :inline="true" :model="integralDetailInfo.conditions" class="search-form text-left">
  28 + <el-form-item>
  29 + <el-input v-model="integralDetailInfo.conditions.integralNameLike"
  30 + :placeholder="$t('integralDetail.accountPlaceholder')" clearable />
  31 + </el-form-item>
  32 + <el-form-item>
  33 + <el-select v-model="integralDetailInfo.conditions.detailType"
  34 + :placeholder="$t('integralDetail.typePlaceholder')">
  35 + <el-option :label="$t('integralDetail.all')" value="" />
  36 + <el-option :label="$t('integralDetail.transferIn')" value="1001" />
  37 + <el-option :label="$t('integralDetail.transferOut')" value="2002" />
  38 + </el-select>
  39 + </el-form-item>
  40 + <el-form-item>
  41 + <el-select v-model="integralDetailInfo.conditions.objType"
  42 + :placeholder="$t('integralDetail.objectTypePlaceholder')">
  43 + <el-option :label="$t('integralDetail.all')" value="" />
  44 + <el-option :label="$t('integralDetail.user')" value="6006" />
  45 + <el-option :label="$t('integralDetail.merchant')" value="7007" />
  46 + </el-select>
  47 + </el-form-item>
  48 + <el-form-item>
  49 + <el-input v-model="integralDetailInfo.conditions.orderId"
  50 + :placeholder="$t('integralDetail.orderIdPlaceholder')" clearable />
  51 + </el-form-item>
  52 + <el-form-item>
  53 + <el-button type="primary" @click="_queryIntegralDetailMethod">
  54 + <i class="el-icon-search"></i>
  55 + {{ $t('common.search') }}
  56 + </el-button>
  57 + </el-form-item>
  58 + </el-form>
  59 + </el-card>
  60 +
  61 + <el-card class="table-card">
  62 + <div slot="header" class="clearfix text-left">
  63 + <span>{{ $t('integralDetail.tableTitle') }}</span>
  64 + </div>
  65 + <el-table :data="integralDetailInfo.integralDetails" border style="width: 100%" v-loading="loading">
  66 + <el-table-column prop="detailId" :label="$t('integralDetail.id')" align="center" width="80" />
  67 + <el-table-column prop="integralName" :label="$t('integralDetail.accountName')" align="center" />
  68 + <el-table-column prop="integralId" :label="$t('integralDetail.accountId')" align="center" />
  69 + <el-table-column :label="$t('integralDetail.type')" align="center">
  70 + <template slot-scope="scope">
  71 + {{ scope.row.detailType === '2002' ? $t('integralDetail.transferOut') : $t('integralDetail.transferIn') }}
  72 + </template>
  73 + </el-table-column>
  74 + <el-table-column prop="relIntegralId" :label="$t('integralDetail.relatedAccount')" align="center" />
  75 + <el-table-column prop="amount" :label="$t('integralDetail.points')" align="center" />
  76 + <el-table-column :label="$t('integralDetail.objectType')" align="center">
  77 + <template slot-scope="scope">
  78 + {{ scope.row.objType === '7007' ? $t('integralDetail.merchant') : $t('integralDetail.user') }}
  79 + </template>
  80 + </el-table-column>
  81 + <el-table-column prop="objId" :label="$t('integralDetail.objectId')" align="center" />
  82 + <el-table-column prop="link" :label="$t('integralDetail.phone')" align="center" />
  83 + <el-table-column prop="orderId" :label="$t('integralDetail.orderId')" align="center" />
  84 + <el-table-column prop="createTime" :label="$t('integralDetail.transactionTime')" align="center" />
  85 + <el-table-column prop="remark" :label="$t('integralDetail.remark')" align="center" />
  86 + </el-table>
  87 + <el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange"
  88 + :current-page="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  89 + layout="total, sizes, prev, pager, next, jumper" :total="page.total" class="pagination">
  90 + </el-pagination>
  91 + </el-card>
  92 + </el-col>
  93 + </el-row>
  94 + </div>
  95 +</template>
  96 +
  97 +<script>
  98 +import { getIntegralDetailList } from '@/api/mall/integralDetailApi'
  99 +
  100 +export default {
  101 + name: 'IntegralDetailList',
  102 + data() {
  103 + return {
  104 + loading: false,
  105 + integralDetailInfo: {
  106 + integralDetails: [],
  107 + conditions: {
  108 + integralId: '',
  109 + detailType: '',
  110 + integralNameLike: '',
  111 + amount: '',
  112 + objType: '',
  113 + orderId: '',
  114 + mallApiCode: 'queryIntegralDetailBmoImpl'
  115 + }
  116 + },
  117 + page: {
  118 + current: 1,
  119 + size: 10,
  120 + total: 0
  121 + }
  122 + }
  123 + },
  124 + created() {
  125 + this._listIntegralDetails(this.page.current, this.page.size)
  126 + },
  127 + methods: {
  128 + async _listIntegralDetails(page, size) {
  129 + try {
  130 + this.loading = true
  131 + this.integralDetailInfo.conditions.page = page
  132 + this.integralDetailInfo.conditions.row = size
  133 +
  134 + const { data, total } = await getIntegralDetailList(this.integralDetailInfo.conditions)
  135 + this.integralDetailInfo.integralDetails = data
  136 + this.page.total = total
  137 + } catch (error) {
  138 + this.$message.error(this.$t('integralDetail.fetchError'))
  139 + } finally {
  140 + this.loading = false
  141 + }
  142 + },
  143 + _queryIntegralDetailMethod() {
  144 + this.page.current = 1
  145 + this._listIntegralDetails(this.page.current, this.page.size)
  146 + },
  147 + _switchIntegralObjType(objType) {
  148 + this.integralDetailInfo.conditions.objType = objType
  149 + this._listIntegralDetails(this.page.current, this.page.size)
  150 + },
  151 + handleSizeChange(val) {
  152 + this.page.size = val
  153 + this._listIntegralDetails(this.page.current, this.page.size)
  154 + },
  155 + handleCurrentChange(val) {
  156 + this.page.current = val
  157 + this._listIntegralDetails(this.page.current, this.page.size)
  158 + }
  159 + }
  160 +}
  161 +</script>
  162 +
  163 +<style lang="scss" scoped>
  164 +.integral-detail-container {
  165 + padding: 20px;
  166 +
  167 + .tree-card {
  168 + height: 100%;
  169 +
  170 + .tree-list {
  171 + list-style: none;
  172 + padding: 0;
  173 + margin: 0;
  174 +
  175 + .tree-item {
  176 + padding: 10px;
  177 + margin-bottom: 5px;
  178 + text-align: center;
  179 + cursor: pointer;
  180 + border-radius: 4px;
  181 +
  182 + &:hover {
  183 + background-color: #f5f7fa;
  184 + }
  185 +
  186 + &.active {
  187 + background-color: #409eff;
  188 + color: white;
  189 + }
  190 + }
  191 + }
  192 + }
  193 +
  194 + .search-card {
  195 + margin-bottom: 20px;
  196 +
  197 + .search-form {
  198 + .el-form-item {
  199 + margin-bottom: 0;
  200 + }
  201 + }
  202 + }
  203 +
  204 + .pagination {
  205 + margin-top: 20px;
  206 + text-align: right;
  207 + }
  208 +}
  209 +</style>
0 210 \ No newline at end of file
... ...
src/views/mall/productSjLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + productSj: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + prodName: 'Please enter product name'
  7 + },
  8 + list: {
  9 + title: 'Shelved Products',
  10 + today: 'Today',
  11 + all: 'All Shelved'
  12 + },
  13 + table: {
  14 + productId: 'Product ID',
  15 + coverPhoto: 'Product Image',
  16 + categoryName: 'Product Category',
  17 + prodName: 'Product Name',
  18 + sales: 'Sales',
  19 + stock: 'Stock',
  20 + price: 'Price',
  21 + sort: 'Sort',
  22 + state: 'Status'
  23 + },
  24 + fetchError: 'Failed to fetch product list'
  25 + }
  26 + },
  27 + zh: {
  28 + productSj: {
  29 + search: {
  30 + title: '查询条件',
  31 + prodName: '请输入商品名称'
  32 + },
  33 + list: {
  34 + title: '上架商品',
  35 + today: '今日上架',
  36 + all: '所有上架'
  37 + },
  38 + table: {
  39 + productId: '商品ID',
  40 + coverPhoto: '商品图片',
  41 + categoryName: '商品分组',
  42 + prodName: '商品名称',
  43 + sales: '销量',
  44 + stock: '库存',
  45 + price: '价格',
  46 + sort: '排序',
  47 + state: '状态'
  48 + },
  49 + fetchError: '获取商品列表失败'
  50 + }
  51 + }
  52 +}
0 53 \ No newline at end of file
... ...
src/views/mall/productSjList.vue 0 → 100644
  1 +<template>
  2 + <div class="product-sj-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="clearfix text-left">
  6 + <span>{{ $t('productSj.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input
  11 + v-model="searchForm.prodName"
  12 + :placeholder="$t('productSj.search.prodName')"
  13 + clearable
  14 + @keyup.enter.native="handleSearch"
  15 + />
  16 + </el-col>
  17 + <el-col :span="2">
  18 + <el-button type="primary" @click="handleSearch">
  19 + {{ $t('common.search') }}
  20 + </el-button>
  21 + </el-col>
  22 + </el-row>
  23 + </el-card>
  24 +
  25 + <!-- 商品列表 -->
  26 + <el-card class="list-wrapper">
  27 + <div slot="header" class="clearfix text-left">
  28 + <span>{{ $t('productSj.list.title') }}</span>
  29 + <div style="float: right;">
  30 + <el-button type="primary" size="small" @click="listProductsToDay">
  31 + <i class="el-icon-plus"></i>
  32 + {{ $t('productSj.list.today') }}
  33 + </el-button>
  34 + <el-button type="primary" size="small" style="margin-left: 10px" @click="listProductsAll">
  35 + {{ $t('productSj.list.all') }}
  36 + </el-button>
  37 + </div>
  38 + </div>
  39 +
  40 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  41 + <el-table-column prop="productId" :label="$t('productSj.table.productId')" align="center" />
  42 + <el-table-column :label="$t('productSj.table.coverPhoto')" align="center">
  43 + <template slot-scope="scope">
  44 + <el-image
  45 + style="width: 60px; height: 60px; border-radius: 5px;"
  46 + :src="scope.row.coverPhoto"
  47 + fit="cover"
  48 + />
  49 + </template>
  50 + </el-table-column>
  51 + <el-table-column prop="categoryName" :label="$t('productSj.table.categoryName')" align="center" />
  52 + <el-table-column prop="prodName" :label="$t('productSj.table.prodName')" align="center" />
  53 + <el-table-column prop="sales" :label="$t('productSj.table.sales')" align="center" />
  54 + <el-table-column prop="stock" :label="$t('productSj.table.stock')" align="center" />
  55 + <el-table-column :label="$t('productSj.table.price')" align="center">
  56 + <template slot-scope="scope">
  57 + {{ scope.row.defaultSpecValue.price }}
  58 + </template>
  59 + </el-table-column>
  60 + <el-table-column prop="sort" :label="$t('productSj.table.sort')" align="center" />
  61 + <el-table-column prop="stateName" :label="$t('productSj.table.state')" align="center" />
  62 + </el-table>
  63 +
  64 + <el-pagination
  65 + :current-page.sync="page.current"
  66 + :page-sizes="[10, 20, 30, 50]"
  67 + :page-size="page.size"
  68 + :total="page.total"
  69 + layout="total, sizes, prev, pager, next, jumper"
  70 + @size-change="handleSizeChange"
  71 + @current-change="handleCurrentChange"
  72 + />
  73 + </el-card>
  74 +
  75 + <delete-product ref="deleteProduct" @success="handleSuccess" />
  76 + </div>
  77 +</template>
  78 +
  79 +<script>
  80 +import { getAdminProductList } from '@/api/mall/productSjApi'
  81 +import DeleteProduct from '@/components/mall/DeleteProduct'
  82 +
  83 +export default {
  84 + name: 'ProductSjList',
  85 + components: {
  86 + DeleteProduct
  87 + },
  88 + data() {
  89 + return {
  90 + loading: false,
  91 + searchForm: {
  92 + prodName: '',
  93 + state: '2002',
  94 + keyword: '',
  95 + barCode: '',
  96 + createTime: '',
  97 + mallApiCode: 'queryAdminProductBmoImpl'
  98 + },
  99 + tableData: [],
  100 + page: {
  101 + current: 1,
  102 + size: 10,
  103 + total: 0
  104 + }
  105 + }
  106 + },
  107 + created() {
  108 + this.getList()
  109 + },
  110 + methods: {
  111 + async getList() {
  112 + try {
  113 + this.loading = true
  114 + const params = {
  115 + page: this.page.current,
  116 + row: this.page.size,
  117 + ...this.searchForm
  118 + }
  119 + const { data, total } = await getAdminProductList(params)
  120 + this.tableData = data
  121 + this.page.total = total
  122 + } catch (error) {
  123 + this.$message.error(this.$t('productSj.fetchError'))
  124 + } finally {
  125 + this.loading = false
  126 + }
  127 + },
  128 + handleSearch() {
  129 + this.page.current = 1
  130 + this.getList()
  131 + },
  132 + listProductsToDay() {
  133 + this.searchForm.createTime = this.$dayjs().format('YYYY-MM-DD HH:mm:ss')
  134 + this.handleSearch()
  135 + },
  136 + listProductsAll() {
  137 + this.searchForm.createTime = ''
  138 + this.handleSearch()
  139 + },
  140 + handleSizeChange(val) {
  141 + this.page.size = val
  142 + this.getList()
  143 + },
  144 + handleCurrentChange(val) {
  145 + this.page.current = val
  146 + this.getList()
  147 + },
  148 + handleSuccess() {
  149 + this.getList()
  150 + }
  151 + }
  152 +}
  153 +</script>
  154 +
  155 +<style lang="scss" scoped>
  156 +.product-sj-container {
  157 + padding: 0;
  158 + margin: 0;
  159 +
  160 + .search-wrapper {
  161 + margin-bottom: 20px;
  162 + }
  163 +
  164 + .list-wrapper {
  165 + .el-pagination {
  166 + margin-top: 20px;
  167 + text-align: right;
  168 + }
  169 + }
  170 +}
  171 +</style>
0 172 \ No newline at end of file
... ...
src/views/mall/storeOrderCartManageLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + storeOrderCartManage: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + cartId: 'Order Number',
  7 + state: 'Select Status',
  8 + prodName: 'Enter Product Name',
  9 + shop: 'Select Shop'
  10 + },
  11 + list: {
  12 + title: 'Order Information'
  13 + },
  14 + table: {
  15 + cartId: 'Order Number',
  16 + appName: 'Platform',
  17 + shopName: 'Shop',
  18 + cartType: 'Type',
  19 + service: 'Service',
  20 + goods: 'Goods',
  21 + prodName: 'Name',
  22 + cartNum: 'Quantity',
  23 + personName: 'User Name',
  24 + payPrice: 'Payment Amount',
  25 + stateName: 'Order Status',
  26 + createTime: 'Creation Time'
  27 + },
  28 + state: {
  29 + unpurchased: 'Unpurchased',
  30 + waitingDelivery: 'Waiting Delivery',
  31 + waitingReceive: 'Waiting Receive',
  32 + waitingComment: 'Waiting Comment',
  33 + applyRefund: 'Apply Refund',
  34 + refundSuccess: 'Refund Success',
  35 + refunded: 'Refunded'
  36 + },
  37 + fetchError: 'Failed to fetch order list',
  38 + fetchShopsError: 'Failed to fetch shops'
  39 + }
  40 + },
  41 + zh: {
  42 + storeOrderCartManage: {
  43 + search: {
  44 + title: '查询条件',
  45 + cartId: '订单编号',
  46 + state: '请选择状态',
  47 + prodName: '请输入商品名称',
  48 + shop: '请选择商铺'
  49 + },
  50 + list: {
  51 + title: '订单信息'
  52 + },
  53 + table: {
  54 + cartId: '订单号',
  55 + appName: '平台',
  56 + shopName: '商铺',
  57 + cartType: '类型',
  58 + service: '服务',
  59 + goods: '商品',
  60 + prodName: '名称',
  61 + cartNum: '数量',
  62 + personName: '用户名称',
  63 + payPrice: '支付金额',
  64 + stateName: '订单状态',
  65 + createTime: '创建时间'
  66 + },
  67 + state: {
  68 + unpurchased: '未购买',
  69 + waitingDelivery: '待发货',
  70 + waitingReceive: '待收货',
  71 + waitingComment: '待评价',
  72 + applyRefund: '申请退款',
  73 + refundSuccess: '退货成功',
  74 + refunded: '已退款'
  75 + },
  76 + fetchError: '获取订单列表失败',
  77 + fetchShopsError: '获取商铺列表失败'
  78 + }
  79 + }
  80 +}
0 81 \ No newline at end of file
... ...
src/views/mall/storeOrderCartManageList.vue 0 → 100644
  1 +<template>
  2 + <div class="store-order-cart-manage-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="clearfix text-left">
  6 + <span>{{ $t('storeOrderCartManage.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="4">
  10 + <el-input v-model="searchForm.cartId" :placeholder="$t('storeOrderCartManage.search.cartId')" clearable />
  11 + </el-col>
  12 + <el-col :span="4">
  13 + <el-select v-model="searchForm.state" :placeholder="$t('storeOrderCartManage.search.state')" clearable>
  14 + <el-option v-for="item in stateOptions" :key="item.value" :label="item.label" :value="item.value" />
  15 + </el-select>
  16 + </el-col>
  17 + <el-col :span="4">
  18 + <el-input v-model="searchForm.prodName" :placeholder="$t('storeOrderCartManage.search.prodName')" clearable />
  19 + </el-col>
  20 + <el-col :span="4">
  21 + <el-select v-model="searchForm.shopId" :placeholder="$t('storeOrderCartManage.search.shop')" clearable>
  22 + <el-option v-for="item in shops" :key="item.shopId" :label="item.shopName" :value="item.shopId" />
  23 + </el-select>
  24 + </el-col>
  25 + <el-col :span="4" >
  26 + <el-button type="primary" @click="handleSearch">
  27 + {{ $t('common.search') }}
  28 + </el-button>
  29 + </el-col>
  30 + </el-row>
  31 + </el-card>
  32 +
  33 + <!-- 订单列表 -->
  34 + <el-card class="list-wrapper">
  35 + <div slot="header" class="clearfix text-left">
  36 + <span>{{ $t('storeOrderCartManage.list.title') }}</span>
  37 + </div>
  38 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  39 + <el-table-column prop="cartId" :label="$t('storeOrderCartManage.table.cartId')" align="center" />
  40 + <el-table-column prop="appName" :label="$t('storeOrderCartManage.table.appName')" align="center" />
  41 + <el-table-column prop="shopName" :label="$t('storeOrderCartManage.table.shopName')" align="center" />
  42 + <el-table-column :label="$t('storeOrderCartManage.table.cartType')" align="center">
  43 + <template slot-scope="scope">
  44 + {{ scope.row.cartType === '3307' ? $t('storeOrderCartManage.table.service') :
  45 + $t('storeOrderCartManage.table.goods') }}
  46 + </template>
  47 + </el-table-column>
  48 + <el-table-column :label="$t('storeOrderCartManage.table.prodName')" align="center">
  49 + <template slot-scope="scope">
  50 + {{ scope.row.prodName }}
  51 + <span v-if="scope.row.cartType !== '3307'">({{ scope.row.specValue }})</span>
  52 + </template>
  53 + </el-table-column>
  54 + <el-table-column prop="cartNum" :label="$t('storeOrderCartManage.table.cartNum')" align="center" />
  55 + <el-table-column prop="personName" :label="$t('storeOrderCartManage.table.personName')" align="center" />
  56 + <el-table-column prop="payPrice" :label="$t('storeOrderCartManage.table.payPrice')" align="center" />
  57 + <el-table-column prop="stateName" :label="$t('storeOrderCartManage.table.stateName')" align="center" />
  58 + <el-table-column prop="createTime" :label="$t('storeOrderCartManage.table.createTime')" align="center" />
  59 + </el-table>
  60 +
  61 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  62 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  63 + @current-change="handleCurrentChange" />
  64 + </el-card>
  65 + </div>
  66 +</template>
  67 +
  68 +<script>
  69 +import { queryAdminStoreOrderCart, queryShopsByAdmin } from '@/api/mall/storeOrderCartManageApi'
  70 +
  71 +export default {
  72 + name: 'StoreOrderCartManageList',
  73 + data() {
  74 + return {
  75 + loading: false,
  76 + searchForm: {
  77 + cartId: '',
  78 + state: '',
  79 + shopId: '',
  80 + prodName: '',
  81 + mallApiCode: 'queryAdminStoreOrderCartBmoImpl'
  82 + },
  83 + stateOptions: [
  84 + { value: '1001', label: this.$t('storeOrderCartManage.state.unpurchased') },
  85 + { value: '2002', label: this.$t('storeOrderCartManage.state.waitingDelivery') },
  86 + { value: '3003', label: this.$t('storeOrderCartManage.state.waitingReceive') },
  87 + { value: '4004', label: this.$t('storeOrderCartManage.state.waitingComment') },
  88 + { value: '5005', label: this.$t('storeOrderCartManage.state.applyRefund') },
  89 + { value: '6006', label: this.$t('storeOrderCartManage.state.refundSuccess') },
  90 + { value: '7007', label: this.$t('storeOrderCartManage.state.refunded') }
  91 + ],
  92 + shops: [],
  93 + tableData: [],
  94 + page: {
  95 + current: 1,
  96 + size: 10,
  97 + total: 0
  98 + }
  99 + }
  100 + },
  101 + created() {
  102 + this.getList()
  103 + this.getShops()
  104 + },
  105 + methods: {
  106 + async getList() {
  107 + try {
  108 + this.loading = true
  109 + const params = {
  110 + ...this.searchForm,
  111 + page: this.page.current,
  112 + row: this.page.size
  113 + }
  114 + const { data, total } = await queryAdminStoreOrderCart(params)
  115 + this.tableData = data
  116 + this.page.total = total
  117 + } catch (error) {
  118 + this.$message.error(this.$t('storeOrderCartManage.fetchError'))
  119 + } finally {
  120 + this.loading = false
  121 + }
  122 + },
  123 + async getShops() {
  124 + try {
  125 + const params = {
  126 + page: 1,
  127 + row: 100,
  128 + mallApiCode: 'queryShopsByAdminBmoImpl'
  129 + }
  130 + const { data } = await queryShopsByAdmin(params)
  131 + this.shops = data
  132 + } catch (error) {
  133 + this.$message.error(this.$t('storeOrderCartManage.fetchShopsError'))
  134 + }
  135 + },
  136 + handleSearch() {
  137 + this.page.current = 1
  138 + this.getList()
  139 + },
  140 + handleSizeChange(val) {
  141 + this.page.size = val
  142 + this.getList()
  143 + },
  144 + handleCurrentChange(val) {
  145 + this.page.current = val
  146 + this.getList()
  147 + }
  148 + }
  149 +}
  150 +</script>
  151 +
  152 +<style lang="scss" scoped>
  153 +.store-order-cart-manage-container {
  154 + padding: 20px;
  155 +
  156 + .search-wrapper {
  157 + margin-bottom: 20px;
  158 + }
  159 +
  160 + .list-wrapper {
  161 + margin-bottom: 20px;
  162 + }
  163 +
  164 + .el-pagination {
  165 + margin-top: 20px;
  166 + text-align: right;
  167 + }
  168 +}
  169 +</style>
0 170 \ No newline at end of file
... ...
src/views/mall/storeOrderCartReturnLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + storeOrderCartReturn: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + cartId: 'Order Number',
  7 + state: 'Please select status',
  8 + prodName: 'Please enter product name'
  9 + },
  10 + list: {
  11 + title: 'Return Orders'
  12 + },
  13 + table: {
  14 + cartId: 'Order Number',
  15 + prodName: 'Product Name',
  16 + specValue: 'Product Specification',
  17 + personName: 'User Name',
  18 + returnPayPrice: 'Refund Amount',
  19 + stateName: 'Order Status',
  20 + returnReason: 'Refund Reason',
  21 + createTime: 'Application Time'
  22 + },
  23 + state: {
  24 + all: 'All Status',
  25 + applyRefund: 'Apply for Refund',
  26 + returnSuccess: 'Return Success',
  27 + refunded: 'Refunded'
  28 + },
  29 + fetchError: 'Failed to fetch return orders'
  30 + }
  31 + },
  32 + zh: {
  33 + storeOrderCartReturn: {
  34 + search: {
  35 + title: '查询条件',
  36 + cartId: '订单编号',
  37 + state: '请选择状态',
  38 + prodName: '请输入商品名称'
  39 + },
  40 + list: {
  41 + title: '退货订单'
  42 + },
  43 + table: {
  44 + cartId: '订单号',
  45 + prodName: '商品名称',
  46 + specValue: '商品规格',
  47 + personName: '用户名称',
  48 + returnPayPrice: '退款金额',
  49 + stateName: '订单状态',
  50 + returnReason: '退款原因',
  51 + createTime: '申请时间'
  52 + },
  53 + state: {
  54 + all: '全部状态',
  55 + applyRefund: '申请退款',
  56 + returnSuccess: '退货成功',
  57 + refunded: '已退款'
  58 + },
  59 + fetchError: '获取退货订单失败'
  60 + }
  61 + }
  62 +}
0 63 \ No newline at end of file
... ...
src/views/mall/storeOrderCartReturnList.vue 0 → 100644
  1 +<template>
  2 + <div class="store-order-cart-return-container">
  3 + <!-- 查询条件 -->
  4 + <el-card class="search-wrapper">
  5 + <div slot="header" class="clearfix text-left">
  6 + <span>{{ $t('storeOrderCartReturn.search.title') }}</span>
  7 + </div>
  8 + <el-row :gutter="20">
  9 + <el-col :span="6">
  10 + <el-input v-model="searchForm.cartId" :placeholder="$t('storeOrderCartReturn.search.cartId')" clearable
  11 + @keyup.enter.native="handleSearch" />
  12 + </el-col>
  13 + <el-col :span="6">
  14 + <el-select v-model="searchForm.state" :placeholder="$t('storeOrderCartReturn.search.state')" clearable>
  15 + <el-option v-for="item in stateOptions" :key="item.value" :label="item.label" :value="item.value" />
  16 + </el-select>
  17 + </el-col>
  18 + <el-col :span="6">
  19 + <el-input v-model="searchForm.prodName" :placeholder="$t('storeOrderCartReturn.search.prodName')" clearable
  20 + @keyup.enter.native="handleSearch" />
  21 + </el-col>
  22 + <el-col :span="6">
  23 + <el-button type="primary" @click="handleSearch">
  24 + {{ $t('common.search') }}
  25 + </el-button>
  26 + </el-col>
  27 + </el-row>
  28 + </el-card>
  29 +
  30 + <!-- 退货订单列表 -->
  31 + <el-card class="list-wrapper">
  32 + <div slot="header" class="clearfix text-left">
  33 + <span>{{ $t('storeOrderCartReturn.list.title') }}</span>
  34 + </div>
  35 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  36 + <el-table-column prop="cartId" :label="$t('storeOrderCartReturn.table.cartId')" align="center" />
  37 + <el-table-column prop="prodName" :label="$t('storeOrderCartReturn.table.prodName')" align="center" />
  38 + <el-table-column prop="specValue" :label="$t('storeOrderCartReturn.table.specValue')" align="center" />
  39 + <el-table-column prop="personName" :label="$t('storeOrderCartReturn.table.personName')" align="center" />
  40 + <el-table-column prop="returnPayPrice" :label="$t('storeOrderCartReturn.table.returnPayPrice')" align="center" />
  41 + <el-table-column prop="stateName" :label="$t('storeOrderCartReturn.table.stateName')" align="center" />
  42 + <el-table-column prop="returnReason" :label="$t('storeOrderCartReturn.table.returnReason')" align="center" />
  43 + <el-table-column prop="createTime" :label="$t('storeOrderCartReturn.table.createTime')" align="center" />
  44 + </el-table>
  45 +
  46 + <el-pagination :current-page.sync="page.current" :page-sizes="[10, 20, 30, 50]" :page-size="page.size"
  47 + :total="page.total" layout="total, sizes, prev, pager, next, jumper" @size-change="handleSizeChange"
  48 + @current-change="handleCurrentChange" />
  49 + </el-card>
  50 + </div>
  51 +</template>
  52 +
  53 +<script>
  54 +import { getStoreOrderCartReturnList } from '@/api/mall/storeOrderCartReturnApi'
  55 +
  56 +export default {
  57 + name: 'StoreOrderCartReturnList',
  58 + data() {
  59 + return {
  60 + loading: false,
  61 + searchForm: {
  62 + cartId: '',
  63 + state: '',
  64 + prodName: '',
  65 + mallApiCode: 'queryStoreOrderCartReturnBmoImpl'
  66 + },
  67 + stateOptions: [
  68 + { value: '', label: this.$t('storeOrderCartReturn.state.all') },
  69 + { value: '5005', label: this.$t('storeOrderCartReturn.state.applyRefund') },
  70 + { value: '6006', label: this.$t('storeOrderCartReturn.state.returnSuccess') },
  71 + { value: '7007', label: this.$t('storeOrderCartReturn.state.refunded') }
  72 + ],
  73 + tableData: [],
  74 + page: {
  75 + current: 1,
  76 + size: 10,
  77 + total: 0
  78 + }
  79 + }
  80 + },
  81 + created() {
  82 + this.getList()
  83 + },
  84 + methods: {
  85 + async getList() {
  86 + try {
  87 + this.loading = true
  88 + const params = {
  89 + ...this.searchForm,
  90 + page: this.page.current,
  91 + row: this.page.size
  92 + }
  93 + const { data, total } = await getStoreOrderCartReturnList(params)
  94 + this.tableData = data.map(item => {
  95 + let specValue = ''
  96 + if (item.productSpecDetails) {
  97 + item.productSpecDetails.forEach(detail => {
  98 + specValue += (detail.detailValue + '/')
  99 + })
  100 + }
  101 + return {
  102 + ...item,
  103 + specValue
  104 + }
  105 + })
  106 + this.page.total = total
  107 + } catch (error) {
  108 + this.$message.error(this.$t('storeOrderCartReturn.fetchError'))
  109 + } finally {
  110 + this.loading = false
  111 + }
  112 + },
  113 + handleSearch() {
  114 + this.page.current = 1
  115 + this.getList()
  116 + },
  117 + handleSizeChange(val) {
  118 + this.page.size = val
  119 + this.getList()
  120 + },
  121 + handleCurrentChange(val) {
  122 + this.page.current = val
  123 + this.getList()
  124 + }
  125 + }
  126 +}
  127 +</script>
  128 +
  129 +<style lang="scss" scoped>
  130 +.store-order-cart-return-container {
  131 + padding: 20px;
  132 +
  133 + .search-wrapper {
  134 + margin-bottom: 20px;
  135 +
  136 + .el-select {
  137 + width: 100%;
  138 + }
  139 + }
  140 +
  141 + .el-pagination {
  142 + margin-top: 20px;
  143 + text-align: right;
  144 + }
  145 +}
  146 +</style>
0 147 \ No newline at end of file
... ...
src/views/mall/userIntegralLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + userIntegral: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + integralName: 'Account Name',
  7 + integralNamePlaceholder: 'Please enter account name'
  8 + },
  9 + list: {
  10 + title: 'User Points'
  11 + },
  12 + table: {
  13 + id: 'ID',
  14 + name: 'Account Name',
  15 + type: 'Object Type',
  16 + userId: 'User ID',
  17 + phone: 'Phone',
  18 + amount: 'Points'
  19 + },
  20 + type: {
  21 + personal: 'Personal',
  22 + merchant: 'Merchant'
  23 + },
  24 + fetchError: 'Failed to fetch points data'
  25 + },
  26 + common: {
  27 + search: 'Search',
  28 + manage: 'Manage'
  29 + }
  30 + },
  31 + zh: {
  32 + userIntegral: {
  33 + search: {
  34 + title: '查询条件',
  35 + integralName: '账户名称',
  36 + integralNamePlaceholder: '请输入账户名称'
  37 + },
  38 + list: {
  39 + title: '用户积分'
  40 + },
  41 + table: {
  42 + id: '编号',
  43 + name: '账户名称',
  44 + type: '对象类型',
  45 + userId: '用户编号',
  46 + phone: '手机号',
  47 + amount: '积分数'
  48 + },
  49 + type: {
  50 + personal: '个人',
  51 + merchant: '商户'
  52 + },
  53 + fetchError: '获取积分数据失败'
  54 + },
  55 + common: {
  56 + search: '查询',
  57 + manage: '管理'
  58 + }
  59 + }
  60 +}
0 61 \ No newline at end of file
... ...
src/views/mall/userIntegralList.vue 0 → 100644
  1 +<template>
  2 + <div class="user-integral-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="3">
  5 + <el-card class="box-card">
  6 + <div class="type-selector">
  7 + <ul class="type-list">
  8 + <li v-for="type in integralTypes" :key="type.value" class="type-item"
  9 + :class="{ 'active': searchForm.objType === type.value }" @click="switchIntegralType(type.value)">
  10 + {{ $t(`userIntegral.type.${type.label}`) }}
  11 + </li>
  12 + </ul>
  13 + </div>
  14 + </el-card>
  15 + </el-col>
  16 + <el-col :span="21">
  17 + <el-card class="box-card">
  18 + <div slot="header" class="clearfix text-left">
  19 + <span>{{ $t('userIntegral.search.title') }}</span>
  20 + </div>
  21 + <el-form :inline="true" :model="searchForm" class="search-form text-left">
  22 + <el-form-item :label="$t('userIntegral.search.integralName')">
  23 + <el-input v-model="searchForm.integralName" :placeholder="$t('userIntegral.search.integralNamePlaceholder')"
  24 + clearable />
  25 + </el-form-item>
  26 + <el-form-item>
  27 + <el-button type="primary" @click="handleSearch">
  28 + {{ $t('common.search') }}
  29 + </el-button>
  30 + </el-form-item>
  31 + </el-form>
  32 + </el-card>
  33 +
  34 + <el-card class="box-card">
  35 + <div slot="header" class="clearfix text-left">
  36 + <span>{{ $t('userIntegral.list.title') }}</span>
  37 + <el-button type="primary" size="mini" style="float: right;" @click="handleManage">
  38 + {{ $t('common.manage') }}
  39 + </el-button>
  40 + </div>
  41 + <el-table v-loading="loading" :data="tableData" border style="width: 100%">
  42 + <el-table-column prop="integralId" :label="$t('userIntegral.table.id')" align="center" />
  43 + <el-table-column prop="integralName" :label="$t('userIntegral.table.name')" align="center" />
  44 + <el-table-column :label="$t('userIntegral.table.type')" align="center">
  45 + <template slot-scope="scope">
  46 + {{ scope.row.objType === '7007' ? $t('userIntegral.type.merchant') : $t('userIntegral.type.personal') }}
  47 + </template>
  48 + </el-table-column>
  49 + <el-table-column prop="objId" :label="$t('userIntegral.table.userId')" align="center" />
  50 + <el-table-column prop="link" :label="$t('userIntegral.table.phone')" align="center" />
  51 + <el-table-column prop="amount" :label="$t('userIntegral.table.amount')" align="center" />
  52 + </el-table>
  53 + <pagination :current-page="pagination.current" :page-size="pagination.size" :total="pagination.total"
  54 + @size-change="handleSizeChange" @current-change="handleCurrentChange" />
  55 + </el-card>
  56 + </el-col>
  57 + </el-row>
  58 + </div>
  59 +</template>
  60 +
  61 +<script>
  62 +import { queryIntegralList } from '@/api/mall/userIntegralApi'
  63 +import Pagination from '@/components/mall/Pagination'
  64 +
  65 +export default {
  66 + name: 'UserIntegralList',
  67 + components: {
  68 + Pagination
  69 + },
  70 + data() {
  71 + return {
  72 + loading: false,
  73 + integralTypes: [
  74 + { value: '6006', label: 'personal' },
  75 + { value: '7007', label: 'merchant' }
  76 + ],
  77 + searchForm: {
  78 + integralName: '',
  79 + objType: '6006',
  80 + mallApiCode: 'queryIntegralBmoImpl'
  81 + },
  82 + tableData: [],
  83 + pagination: {
  84 + current: 1,
  85 + size: 10,
  86 + total: 0
  87 + }
  88 + }
  89 + },
  90 + created() {
  91 + this.getList()
  92 + },
  93 + methods: {
  94 + async getList() {
  95 + try {
  96 + this.loading = true
  97 + const params = {
  98 + page: this.pagination.current,
  99 + row: this.pagination.size,
  100 + ...this.searchForm
  101 + }
  102 + const { data, total } = await queryIntegralList(params)
  103 + this.tableData = data
  104 + this.pagination.total = total
  105 + } catch (error) {
  106 + this.$message.error(this.$t('userIntegral.fetchError'))
  107 + } finally {
  108 + this.loading = false
  109 + }
  110 + },
  111 + handleSearch() {
  112 + this.pagination.current = 1
  113 + this.getList()
  114 + },
  115 + handleManage() {
  116 + const path = this.searchForm.objType === '6006'
  117 + ? '/pages/admin/userIntegral'
  118 + : '/pages/admin/storeIntegral'
  119 + this.$router.push({ path })
  120 + },
  121 + switchIntegralType(type) {
  122 + this.searchForm.objType = type
  123 + this.handleSearch()
  124 + },
  125 + handleSizeChange(val) {
  126 + this.pagination.size = val
  127 + this.getList()
  128 + },
  129 + handleCurrentChange(val) {
  130 + this.pagination.current = val
  131 + this.getList()
  132 + }
  133 + }
  134 +}
  135 +</script>
  136 +
  137 +<style lang="scss" scoped>
  138 +.user-integral-container {
  139 + padding: 20px;
  140 +
  141 + .box-card {
  142 + margin-bottom: 20px;
  143 + }
  144 +
  145 + .type-selector {
  146 + .type-list {
  147 + list-style: none;
  148 + padding: 0;
  149 + margin: 0;
  150 +
  151 + .type-item {
  152 + padding: 10px;
  153 + text-align: center;
  154 + cursor: pointer;
  155 + border-radius: 4px;
  156 + margin-bottom: 5px;
  157 + transition: all 0.3s;
  158 +
  159 + &:hover {
  160 + background-color: #f5f7fa;
  161 + }
  162 +
  163 + &.active {
  164 + background-color: #409eff;
  165 + color: white;
  166 + }
  167 + }
  168 + }
  169 + }
  170 +
  171 + .search-form {
  172 + margin-bottom: -18px;
  173 + }
  174 +}
  175 +</style>
0 176 \ No newline at end of file
... ...
src/views/user/userLoginLang.js 0 → 100644
  1 +export const messages = {
  2 + en: {
  3 + userLogin: {
  4 + search: {
  5 + title: 'Search Conditions',
  6 + name: 'Please enter staff name',
  7 + tel: 'Please enter phone number',
  8 + startTime: 'Login start time',
  9 + endTime: 'Login end time'
  10 + },
  11 + table: {
  12 + title: 'Login Logs',
  13 + loginId: 'Login ID',
  14 + parentOrgName: 'Company',
  15 + orgName: 'Department',
  16 + userName: 'Name',
  17 + loginTime: 'Login Time',
  18 + userId: 'Staff ID'
  19 + },
  20 + allStores: 'All',
  21 + fetchError: 'Failed to fetch login logs',
  22 + storeFetchError: 'Failed to fetch store list'
  23 + }
  24 + },
  25 + zh: {
  26 + userLogin: {
  27 + search: {
  28 + title: '查询条件',
  29 + name: '请输入员工名称',
  30 + tel: '请输入手机号',
  31 + startTime: '登录开始时间',
  32 + endTime: '登录结束时间'
  33 + },
  34 + table: {
  35 + title: '登录日志',
  36 + loginId: '登录ID',
  37 + parentOrgName: '公司',
  38 + orgName: '部门',
  39 + userName: '名称',
  40 + loginTime: '登录时间',
  41 + userId: '员工ID'
  42 + },
  43 + allStores: '全部',
  44 + fetchError: '获取登录日志失败',
  45 + storeFetchError: '获取门店列表失败'
  46 + }
  47 + }
  48 +}
0 49 \ No newline at end of file
... ...
src/views/user/userLoginList.vue 0 → 100644
  1 +<template>
  2 + <div class="user-login-container">
  3 + <el-row :gutter="20">
  4 + <el-col :span="4">
  5 + <el-card class="store-list-card">
  6 + <div class="store-list">
  7 + <ul class="store-ul">
  8 + <li
  9 + v-for="(item,index) in userLoginInfo.stores"
  10 + :key="index"
  11 + @click="swatchStore(item)"
  12 + :class="{'selected-store':userLoginInfo.conditions.storeId == item.storeId}">
  13 + {{item.name}}<span v-if="item.storeTypeName">({{item.storeTypeName}})</span>
  14 + </li>
  15 + </ul>
  16 + </div>
  17 + </el-card>
  18 + </el-col>
  19 + <el-col :span="20">
  20 + <el-card class="search-card">
  21 + <div slot="header" class="clearfix text-left">
  22 + <span>{{ $t('userLogin.search.title') }}</span>
  23 + </div>
  24 + <el-row :gutter="20">
  25 + <el-col :span="4">
  26 + <el-input
  27 + :placeholder="$t('userLogin.search.name')"
  28 + v-model="userLoginInfo.conditions.name"
  29 + clearable />
  30 + </el-col>
  31 + <el-col :span="4">
  32 + <el-input
  33 + type="number"
  34 + :placeholder="$t('userLogin.search.tel')"
  35 + v-model="userLoginInfo.conditions.tel"
  36 + clearable />
  37 + </el-col>
  38 + <el-col :span="4">
  39 + <el-date-picker
  40 + v-model="userLoginInfo.conditions.startTime"
  41 + type="datetime"
  42 + :placeholder="$t('userLogin.search.startTime')"
  43 + value-format="yyyy-MM-dd HH:mm:ss">
  44 + </el-date-picker>
  45 + </el-col>
  46 + <el-col :span="4">
  47 + <el-date-picker
  48 + v-model="userLoginInfo.conditions.endTime"
  49 + type="datetime"
  50 + :placeholder="$t('userLogin.search.endTime')"
  51 + value-format="yyyy-MM-dd HH:mm:ss">
  52 + </el-date-picker>
  53 + </el-col>
  54 + <el-col :span="4" >
  55 + <el-button type="primary" @click="_queryUserLoginMethod">
  56 + <i class="el-icon-search"></i> {{ $t('common.search') }}
  57 + </el-button>
  58 + </el-col>
  59 + </el-row>
  60 + </el-card>
  61 +
  62 + <el-card class="table-card">
  63 + <div slot="header" class="clearfix text-left">
  64 + <span>{{ $t('userLogin.table.title') }}</span>
  65 + </div>
  66 + <el-table
  67 + v-loading="loading"
  68 + :data="userLoginInfo.logs"
  69 + border
  70 + style="width: 100%">
  71 + <el-table-column
  72 + prop="loginId"
  73 + :label="$t('userLogin.table.loginId')"
  74 + align="center" />
  75 + <el-table-column
  76 + prop="parentOrgName"
  77 + :label="$t('userLogin.table.parentOrgName')"
  78 + align="center">
  79 + <template slot-scope="scope">
  80 + {{ scope.row.parentOrgName || '-' }}
  81 + </template>
  82 + </el-table-column>
  83 + <el-table-column
  84 + prop="orgName"
  85 + :label="$t('userLogin.table.orgName')"
  86 + align="center" />
  87 + <el-table-column
  88 + prop="userName"
  89 + :label="$t('userLogin.table.userName')"
  90 + align="center" />
  91 + <el-table-column
  92 + prop="loginTime"
  93 + :label="$t('userLogin.table.loginTime')"
  94 + align="center" />
  95 + <el-table-column
  96 + prop="userId"
  97 + :label="$t('userLogin.table.userId')"
  98 + align="center" />
  99 + </el-table>
  100 +
  101 + <el-pagination
  102 + @size-change="handleSizeChange"
  103 + @current-change="handleCurrentChange"
  104 + :current-page="pagination.current"
  105 + :page-sizes="[10, 20, 30, 50]"
  106 + :page-size="pagination.size"
  107 + layout="total, sizes, prev, pager, next, jumper"
  108 + :total="pagination.total"
  109 + style="margin-top: 20px;">
  110 + </el-pagination>
  111 + </el-card>
  112 + </el-col>
  113 + </el-row>
  114 + </div>
  115 +</template>
  116 +
  117 +<script>
  118 +import { queryUserLogin, listStores } from '@/api/user/userLoginApi'
  119 +
  120 +export default {
  121 + name: 'UserLoginList',
  122 + data() {
  123 + return {
  124 + loading: false,
  125 + userLoginInfo: {
  126 + logs: [],
  127 + stores: [],
  128 + conditions: {
  129 + name: '',
  130 + tel: '',
  131 + storeId: '',
  132 + startTime: '',
  133 + endTime: '',
  134 + page: 1,
  135 + row: 10
  136 + }
  137 + },
  138 + pagination: {
  139 + current: 1,
  140 + size: 10,
  141 + total: 0
  142 + }
  143 + }
  144 + },
  145 + created() {
  146 + this.loadData()
  147 + this._listListStores()
  148 + },
  149 + methods: {
  150 + async loadData() {
  151 + try {
  152 + this.loading = true
  153 + const params = {
  154 + ...this.userLoginInfo.conditions,
  155 + page: this.pagination.current,
  156 + row: this.pagination.size
  157 + }
  158 + const { data, records } = await queryUserLogin(params)
  159 + this.userLoginInfo.logs = data
  160 + this.pagination.total = records
  161 + } catch (error) {
  162 + this.$message.error(this.$t('userLogin.fetchError'))
  163 + } finally {
  164 + this.loading = false
  165 + }
  166 + },
  167 + async _listListStores() {
  168 + try {
  169 + const params = {
  170 + page: 1,
  171 + row: 100
  172 + }
  173 + const { data } = await listStores(params)
  174 + this.userLoginInfo.stores = [
  175 + { storeId: '', name: this.$t('userLogin.allStores') },
  176 + ...data
  177 + ]
  178 + } catch (error) {
  179 + this.$message.error(this.$t('userLogin.storeFetchError'))
  180 + }
  181 + },
  182 + swatchStore(item) {
  183 + this.userLoginInfo.conditions.storeId = item.storeId
  184 + this.pagination.current = 1
  185 + this.loadData()
  186 + },
  187 + _queryUserLoginMethod() {
  188 + this.pagination.current = 1
  189 + this.loadData()
  190 + },
  191 + handleSizeChange(val) {
  192 + this.pagination.size = val
  193 + this.loadData()
  194 + },
  195 + handleCurrentChange(val) {
  196 + this.pagination.current = val
  197 + this.loadData()
  198 + }
  199 + }
  200 +}
  201 +</script>
  202 +
  203 +<style lang="scss" scoped>
  204 +.user-login-container {
  205 + padding: 20px;
  206 +
  207 + .store-list-card {
  208 + height: 100%;
  209 +
  210 + .store-list {
  211 + .store-ul {
  212 + list-style: none;
  213 + padding: 0;
  214 + margin: 0;
  215 +
  216 + li {
  217 + padding: 10px;
  218 + cursor: pointer;
  219 + border-radius: 4px;
  220 + margin-bottom: 5px;
  221 + text-align: center;
  222 +
  223 + &:hover {
  224 + background-color: #f5f7fa;
  225 + }
  226 +
  227 + &.selected-store {
  228 + background-color: #409eff;
  229 + color: white;
  230 + }
  231 + }
  232 + }
  233 + }
  234 + }
  235 +
  236 + .search-card {
  237 + margin-bottom: 20px;
  238 + }
  239 +}
  240 +</style>
0 241 \ No newline at end of file
... ...