From bb57d646dba55907436b0b8be1235d96f40d0071 Mon Sep 17 00:00:00 2001 From: liqianjin <949671634@qq.com> Date: Mon, 29 May 2023 19:59:31 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .env | 4 +- .../Http/Controllers/InquiryController.php | 145 ++++++++++++ beike/Admin/Repositories/InquiryRepo.php | 131 +++++++++++ beike/Admin/Routes/admin.php | 4 + beike/Admin/Services/ProductService.php | 3 + beike/Helpers.php | 50 +++++ beike/Models/Inquiry.php | 21 ++ beike/Models/Product.php | 19 +- beike/Repositories/InquiryRepo.php | 68 ++++++ beike/Repositories/OrderRepo.php | 9 +- beike/Repositories/ProductRepo.php | 2 +- .../Shop/Http/Controllers/CartController.php | 5 + beike/Shop/Http/Requests/CartRequest.php | 6 +- beike/Shop/Http/Resources/CartDetail.php | 6 +- beike/Shop/Http/Resources/InquiryDetail.php | 39 ++++ beike/Shop/Http/Resources/ProductDetail.php | 2 + beike/Shop/Routes/shop.php | 3 + beike/Shop/Services/InquiryService.php | 24 ++ package-lock.json | 67 ++++++ package.json | 3 + public/build/beike/shop/default/js/app.js | 4 + .../admin/views/pages/inquiry/form.blade.php | 212 ++++++++++++++++++ .../admin/views/pages/inquiry/index.blade.php | 97 ++++++++ .../views/pages/products/form/form.blade.php | 203 ++++++++++++++++- resources/beike/shop/default/js/header.js | 4 + resources/lang/en/admin/page.php | 1 + resources/lang/en/common.php | 4 + resources/lang/en/shop/products.php | 5 + resources/lang/zh_cn/admin/page.php | 2 + resources/lang/zh_cn/admin/product.php | 7 +- resources/lang/zh_cn/common.php | 5 + resources/lang/zh_cn/shop/products.php | 5 + themes/default/cart/mini.blade.php | 4 +- themes/default/product.blade.php | 132 ++++++++++- 34 files changed, 1276 insertions(+), 20 deletions(-) create mode 100644 beike/Admin/Http/Controllers/InquiryController.php create mode 100644 beike/Admin/Repositories/InquiryRepo.php create mode 100644 beike/Models/Inquiry.php create mode 100644 beike/Repositories/InquiryRepo.php create mode 100644 beike/Shop/Http/Resources/InquiryDetail.php create mode 100644 beike/Shop/Services/InquiryService.php create mode 100644 resources/beike/admin/views/pages/inquiry/form.blade.php create mode 100644 resources/beike/admin/views/pages/inquiry/index.blade.php diff --git a/.env b/.env index db4e8122..7c828945 100644 --- a/.env +++ b/.env @@ -1,7 +1,7 @@ -APP_NAME='BeikeShop' +APP_NAME='wyyl' APP_ENV= APP_KEY=base64:PItUypiY6FmV8oQTVIcIHyNQJAuuS36FmEs8exQbYAw= -APP_DEBUG=false +APP_DEBUG=true APP_LOG_LEVEL= APP_URL=http://43.153.17.83 diff --git a/beike/Admin/Http/Controllers/InquiryController.php b/beike/Admin/Http/Controllers/InquiryController.php new file mode 100644 index 00000000..701e2e70 --- /dev/null +++ b/beike/Admin/Http/Controllers/InquiryController.php @@ -0,0 +1,145 @@ + + * @created 2022-08-08 15:07:33 + * @modified 2022-08-08 15:07:33 + */ + +namespace Beike\Admin\Http\Controllers; + +use Beike\Admin\Http\Requests\PageRequest; +use Beike\Admin\Repositories\InquiryRepo; +use Beike\Models\Page; +use Beike\Shop\Http\Resources\InquiryDetail; +use Beike\Shop\Http\Resources\ProductSimple; +use Illuminate\Http\RedirectResponse; +use Illuminate\Http\Request; + +class InquiryController extends Controller +{ + /** + * 显示单页列表 + * + * @return mixed + */ + public function index() + { + $pageList = InquiryRepo::getList(); + $data = [ + 'pages' => $pageList, + 'pages_format' => InquiryDetail::collection($pageList)->jsonSerialize(), + ]; + + return view('admin::pages.inquiry.index', $data); + } + + /** + * 创建页面 + * + * @return mixed + */ + public function create() + { + return view('admin::pages.pages.form', ['page' => new Page()]); + } + + /** + * 保存新建 + * + * @param PageRequest $request + * @return RedirectResponse + */ + public function store(PageRequest $request) + { + try { + $requestData = $request->all(); + $page = PageRepo::createOrUpdate($requestData); + hook_action('admin.page.store.after', ['request_data' => $requestData, 'page' => $page]); + + return redirect(admin_route('pages.index')); + } catch (\Exception $e) { + return redirect(admin_route('pages.index'))->withErrors(['error' => $e->getMessage()]); + } + } + + /** + * @param Request $request + * @param Page $page + * @return mixed + */ + public function edit(Request $request, Page $page) + { + $page->load(['products.description', 'category.description']); + + $data = [ + 'page' => $page, + 'products' => ProductSimple::collection($page->products)->jsonSerialize(), + 'descriptions' => PageRepo::getDescriptionsByLocale($page->id), + ]; + + return view('admin::pages.pages.form', $data); + } + + /** + * 保存更新 + * + * @param PageRequest $request + * @param int $pageId + * @return RedirectResponse + */ + public function update(PageRequest $request, int $pageId) + { + try { + $requestData = $request->all(); + $requestData['id'] = $pageId; + $page = PageRepo::createOrUpdate($requestData); + hook_action('admin.page.update.after', ['request_data' => $requestData, 'page' => $page]); + + return redirect()->to(admin_route('pages.index')); + } catch (\Exception $e) { + return redirect(admin_route('pages.index'))->withErrors(['error' => $e->getMessage()]); + } + } + + /** + * 删除单页 + * + * @param Request $request + * @param int $pageId + * @return array + */ + public function destroy(Request $request, int $pageId): array + { + InquiryRepo::deleteById($pageId); + + return json_success(trans('common.deleted_success')); + } + + /** + * 搜索页面标题自动完成 + * @param Request $request + * @return array + */ + public function autocomplete(Request $request): array + { + $products = PageRepo::autocomplete($request->get('name') ?? ''); + + return json_success(trans('common.get_success'), $products); + } + + /** + * 获取单页名称 + * @param Page $page + * @return array + */ + public function name(Page $page): array + { + $name = $page->description->title ?? ''; + + return json_success(trans('common.get_success'), $name); + } +} diff --git a/beike/Admin/Repositories/InquiryRepo.php b/beike/Admin/Repositories/InquiryRepo.php new file mode 100644 index 00000000..d968afe3 --- /dev/null +++ b/beike/Admin/Repositories/InquiryRepo.php @@ -0,0 +1,131 @@ + + * @created 2022-07-26 21:08:07 + * @modified 2022-07-26 21:08:07 + */ + +namespace Beike\Admin\Repositories; + +use Beike\Models\Inquiry; +use Illuminate\Contracts\Pagination\LengthAwarePaginator; +use Illuminate\Support\Facades\DB; + +class InquiryRepo +{ + /** + * 获取列表页数据 + * + * @return LengthAwarePaginator + */ + public static function getList(): LengthAwarePaginator + { + $builder = Inquiry::query()->with([ + 'productsku', + ])->orderByDesc('updated_at'); + + return $builder->paginate(perPage()); + } + + public static function findByPageId($pageId) + { + $page = Inquiry::query()->findOrFail($pageId); + $page->load(['descriptions']); + + return $page; + } + + public static function getDescriptionsByLocale($pageId) + { + $page = self::findByPageId($pageId); + + return $page->descriptions->keyBy('locale')->toArray(); + } + + public static function createOrUpdate($data) + { + try { + DB::beginTransaction(); + $region = self::pushPage($data); + DB::commit(); + + return $region; + } catch (\Exception $e) { + DB::rollBack(); + + throw $e; + } + } + + public static function pushPage($data) + { + $id = $data['id'] ?? 0; + if ($id) { + $page = Inquiry::query()->findOrFail($id); + } else { + $page = new Inquiry(); + } + $page->fill([ + 'page_category_id' => (int) ($data['page_category_id'] ?? 0), + 'position' => (int) ($data['position'] ?? 0), + 'active' => (bool) ($data['active'] ?? true), + 'author' => $data['author'] ?? '', + 'views' => (int) ($data['views'] ?? 0), + ]); + + $page->saveOrFail(); + + $page->descriptions()->delete(); + $page->descriptions()->createMany($data['descriptions']); + + $products = $data['products'] ?? []; + if ($products) { + $items = []; + foreach ($products as $item) { + $items[] = [ + 'product_id' => $item, + ]; + } + $page->pageProducts()->delete(); + $page->pageProducts()->createMany($items); + } + + $page->load(['descriptions', 'pageProducts']); + + return $page; + } + + public static function deleteById($id) + { + $page = Inquiry::query()->findOrFail($id); + $page->delete(); + } + + /** + * 页面内容自动完成 + * + * @param $name + * @return array + */ + public static function autocomplete($name): array + { + $pages = Inquiry::query()->with('description') + ->whereHas('description', function ($query) use ($name) { + $query->where('title', 'like', "{$name}%"); + })->limit(10)->get(); + $results = []; + foreach ($pages as $page) { + $results[] = [ + 'id' => $page->id, + 'name' => $page->description->title, + 'status' => $page->active, + ]; + } + + return $results; + } +} diff --git a/beike/Admin/Routes/admin.php b/beike/Admin/Routes/admin.php index 5abfda76..6e7a3476 100644 --- a/beike/Admin/Routes/admin.php +++ b/beike/Admin/Routes/admin.php @@ -169,6 +169,10 @@ Route::prefix($adminName) Route::middleware('can:pages_update')->put('pages/{page}', [Controllers\PagesController::class, 'update'])->name('pages.update'); Route::middleware('can:pages_delete')->delete('pages/{page}', [Controllers\PagesController::class, 'destroy'])->name('pages.destroy'); + // 文章 + Route::middleware('can:inquiry_index')->get('inquiry', [Controllers\InquiryController::class, 'index'])->name('inquiry.index'); + Route::middleware('can:inquiry_delete')->delete('inquiry/{page}', [Controllers\InquiryController::class, 'destroy'])->name('inquiry.destroy'); + // 文章分类 Route::middleware('can:page_categories_index')->get('page_categories', [Controllers\PageCategoryController::class, 'index'])->name('page_categories.index'); Route::middleware('can:page_categories_index')->get('page_categories/autocomplete', [Controllers\PageCategoryController::class, 'autocomplete'])->name('page_categories.autocomplete'); diff --git a/beike/Admin/Services/ProductService.php b/beike/Admin/Services/ProductService.php index 9ffcf3ac..629ce470 100644 --- a/beike/Admin/Services/ProductService.php +++ b/beike/Admin/Services/ProductService.php @@ -35,6 +35,7 @@ class ProductService $product->skus()->delete(); $product->descriptions()->delete(); $product->attributes()->delete(); + $product->numPrices()->delete(); } $descriptions = []; @@ -58,6 +59,8 @@ class ProductService } $product->skus()->createMany($skus); + $product->numPrices()->createMany(list_sort_by($data['numPrices'],'num') ?? []); + $product->categories()->sync($data['categories'] ?? []); $product->relations()->sync($data['relations'] ?? []); diff --git a/beike/Helpers.php b/beike/Helpers.php index 6fdb9a4d..562b8e25 100644 --- a/beike/Helpers.php +++ b/beike/Helpers.php @@ -718,3 +718,53 @@ function perPage(): int { return (int) system_setting('base.product_per_page', 20); } +/** + * php多维数组指定列排序 + * @param $list + * @param $field + * @param $sortby + * @return array|false + */ +function list_sort_by($list, $field, $sortby='asc') { + + if(is_array($list)){ //判断是否数组 + + $refer = $resultSet = array(); //初始化数组变量 + + foreach ($list as $i => $data) //foreach数组 + + $refer[$i] = &$data[$field]; //存储要排序的数组字段键和值 + + switch ($sortby) {//进行排序 + + case 'asc': // 正向排序 + + asort($refer); + + break; + + case 'desc':// 逆向排序 + + arsort($refer); + + break; + + case 'nat': // 自然排序 + + natcasesort($refer); + + break; + + } + + foreach ( $refer as $key=> $val)//重新组合排序后的数组 + + $resultSet[] = &$list[$key]; + + return $resultSet; + + } + + return false; + +} diff --git a/beike/Models/Inquiry.php b/beike/Models/Inquiry.php new file mode 100644 index 00000000..20f13b3d --- /dev/null +++ b/beike/Models/Inquiry.php @@ -0,0 +1,21 @@ +belongsTo(ProductSku::class, 'product_sku_id', 'id'); + } + +} diff --git a/beike/Models/Product.php b/beike/Models/Product.php index fd924ed2..4c492b4c 100644 --- a/beike/Models/Product.php +++ b/beike/Models/Product.php @@ -11,14 +11,26 @@ class Product extends Base use HasFactory; use SoftDeletes; - protected $fillable = ['images', 'video', 'position', 'brand_id', 'tax_class_id', 'active', 'variables']; + protected $fillable = ['images', 'video', 'position', 'brand_id', 'tax_class_id', 'active', 'variables', 'price_setting']; protected $casts = [ 'active' => 'boolean', 'variables' => 'array', 'images' => 'array', + 'numPrices' => 'array', ]; + public function getNumPricesByNum($num) + { + $descNumPrices = array_reverse($this->numprices->toArray()); + foreach($descNumPrices as $numprice){ + if($num >= $numprice['num']){ + return $numprice['price']; + } + } + return FALSE; + } + protected $appends = ['image']; public function categories() @@ -46,6 +58,11 @@ class Product extends Base return $this->hasMany(ProductSku::class); } + public function numPrices() + { + return $this->hasMany(ProductNumPrice::class); + } + public function attributes(): HasMany { return $this->hasMany(ProductAttribute::class); diff --git a/beike/Repositories/InquiryRepo.php b/beike/Repositories/InquiryRepo.php new file mode 100644 index 00000000..fe05a582 --- /dev/null +++ b/beike/Repositories/InquiryRepo.php @@ -0,0 +1,68 @@ + + * @created 2022-06-28 15:22:05 + * @modified 2022-06-28 15:22:05 + */ + +namespace Beike\Repositories; + +use Beike\Models\Inquiry; + +class InquiryRepo +{ + /** + * 创建一个address记录 + * @param $data + * @return mixed + */ + public static function create($data) + { + return Inquiry::query()->create($data); + } + + /** + * @param $address + * @param $data + * @return mixed + * @throws \Exception + */ + public static function update($address, $data) + { + if (! $address instanceof Inquiry) { + $address = Inquiry::query()->find($address); + } + if (! $address) { + throw new \Exception("地址id {$address} 不存在"); + } + $address->update($data); + + return $address; + } + + /** + * @param $id + * @return mixed + */ + public static function find($id) + { + return Inquiry::query()->find($id); + } + + /** + * @param $id + * @return void + */ + public static function delete($id) + { + $address = Inquiry::query()->find($id); + if ($address) { + $address->delete(); + } + } + +} diff --git a/beike/Repositories/OrderRepo.php b/beike/Repositories/OrderRepo.php index fbb3a1a5..dc66ede4 100644 --- a/beike/Repositories/OrderRepo.php +++ b/beike/Repositories/OrderRepo.php @@ -200,10 +200,6 @@ class OrderRepo $shippingAddress = Address::query()->findOrFail($shippingAddressId); $paymentAddress = Address::query()->findOrFail($paymentAddressId); - $shippingAddress->country = $shippingAddress->country->name ?? ''; - $shippingAddress->country_id = $shippingAddress->country->id ?? 0; - $paymentAddress->country = $paymentAddress->country->name ?? ''; - $paymentAddress->country_id = $paymentAddress->country->id ?? 0; $email = $customer->email; } else { $shippingAddress = new Address($current['guest_shipping_address'] ?? []); @@ -211,6 +207,11 @@ class OrderRepo $email = $current['guest_shipping_address']['email']; } + $shippingAddress->country = $shippingAddress->country->name ?? ''; + $shippingAddress->country_id = $shippingAddress->country->id ?? 0; + $paymentAddress->country = $paymentAddress->country->name ?? ''; + $paymentAddress->country_id = $paymentAddress->country->id ?? 0; + $shippingMethodCode = $current['shipping_method_code'] ?? ''; $paymentMethodCode = $current['payment_method_code'] ?? ''; diff --git a/beike/Repositories/ProductRepo.php b/beike/Repositories/ProductRepo.php index 34d4582b..61050f2b 100644 --- a/beike/Repositories/ProductRepo.php +++ b/beike/Repositories/ProductRepo.php @@ -39,7 +39,7 @@ class ProductRepo if (is_int($product)) { $product = Product::query()->findOrFail($product); } - $product->load('description', 'skus', 'masterSku', 'brand', 'relations'); + $product->load('description', 'skus', 'masterSku', 'brand', 'relations', 'numPrices');//, 'price_setting', 'numPrices'); hook_filter('repo.product.get_detail', $product); diff --git a/beike/Shop/Http/Controllers/CartController.php b/beike/Shop/Http/Controllers/CartController.php index 3fe5d061..e425c1df 100644 --- a/beike/Shop/Http/Controllers/CartController.php +++ b/beike/Shop/Http/Controllers/CartController.php @@ -85,6 +85,7 @@ class CartController extends Controller */ public function update(CartRequest $request, $cartId): array { + try { $customer = current_customer(); $quantity = (int) $request->get('quantity'); CartService::updateQuantity($customer, $cartId, $quantity); @@ -94,6 +95,10 @@ class CartController extends Controller $data = hook_filter('cart.update.data', $data); return json_success(trans('common.updated_success'), $data); + + } catch (\Exception $e) { + return json_fail($e->getMessage()); + } } /** diff --git a/beike/Shop/Http/Requests/CartRequest.php b/beike/Shop/Http/Requests/CartRequest.php index 2a3ba067..d94f0b54 100644 --- a/beike/Shop/Http/Requests/CartRequest.php +++ b/beike/Shop/Http/Requests/CartRequest.php @@ -38,10 +38,14 @@ class CartRequest extends FormRequest return [ 'sku_id' => 'required|int', 'quantity' => ['required', 'int', function ($attribute, $value, $fail) use ($skuId) { - $skuQuantity = ProductSku::query()->where('id', $skuId)->value('quantity'); + $sku = ProductSku::query()->where('id', $skuId)->first(); + $skuQuantity = $sku->quantity; if ($value > $skuQuantity) { $fail(trans('cart.stock_out')); } + if($sku->product->price_setting == 'num' && $value < $sku->product->numprices[0]->num){ + $fail(trans('shop/products.quantity_error')); + } }], 'buy_now' => 'bool', ]; diff --git a/beike/Shop/Http/Resources/CartDetail.php b/beike/Shop/Http/Resources/CartDetail.php index e8645b68..3038f962 100644 --- a/beike/Shop/Http/Resources/CartDetail.php +++ b/beike/Shop/Http/Resources/CartDetail.php @@ -19,7 +19,11 @@ class CartDetail extends JsonResource { $sku = $this->sku; $product = $sku->product; - $price = $sku->price; + if($product->price_setting == 'num'){ + $price = $product->getNumPricesByNum($this->quantity); + }else{ + $price = $sku->price; + }; $skuCode = $sku->sku; $description = $product->description; $productName = $description->name; diff --git a/beike/Shop/Http/Resources/InquiryDetail.php b/beike/Shop/Http/Resources/InquiryDetail.php new file mode 100644 index 00000000..97792670 --- /dev/null +++ b/beike/Shop/Http/Resources/InquiryDetail.php @@ -0,0 +1,39 @@ + + * @created 2022-08-11 18:45:02 + * @modified 2022-08-11 18:45:02 + */ + +namespace Beike\Shop\Http\Resources; + +use Illuminate\Http\Request; +use Illuminate\Http\Resources\Json\JsonResource; + +class InquiryDetail extends JsonResource +{ + /** + * @param Request $request + * @return array + * @throws \Exception + */ + public function toArray($request): array + { + $productsku = $this->productsku; + + return [ + 'id' => $this->id, + 'product_sku_id' => $this->product_sku_id, + 'contacts' => $this->contacts, + 'email' => $this->email, + 'content' => $this->content, + 'product_sku_sku' => $productsku->sku, + 'created_at' => time_format($this->created_at), + 'updated_at' => time_format($this->updated_at), + ]; + } +} diff --git a/beike/Shop/Http/Resources/ProductDetail.php b/beike/Shop/Http/Resources/ProductDetail.php index 32340a24..05f5dbc8 100644 --- a/beike/Shop/Http/Resources/ProductDetail.php +++ b/beike/Shop/Http/Resources/ProductDetail.php @@ -52,6 +52,8 @@ class ProductDetail extends JsonResource 'skus' => SkuDetail::collection($this->skus)->jsonSerialize(), 'in_wishlist' => $this->inCurrentWishlist->id ?? 0, 'active' => (bool) $this->active, + 'price_setting' => $this->price_setting ?? '', + 'numPrices' => numPricesDetail::collection($this->numprices)->jsonSerialize() ?? '', ]; } diff --git a/beike/Shop/Routes/shop.php b/beike/Shop/Routes/shop.php index 7e5199b1..67b2d27f 100644 --- a/beike/Shop/Routes/shop.php +++ b/beike/Shop/Routes/shop.php @@ -18,6 +18,7 @@ use Beike\Shop\Http\Controllers\CheckoutController; use Beike\Shop\Http\Controllers\CurrencyController; use Beike\Shop\Http\Controllers\FileController; use Beike\Shop\Http\Controllers\HomeController; +use Beike\Shop\Http\Controllers\InquiryController; use Beike\Shop\Http\Controllers\LanguageController; use Beike\Shop\Http\Controllers\PageCategoryController; use Beike\Shop\Http\Controllers\PageController; @@ -68,6 +69,8 @@ Route::prefix('/') Route::get('plugin/{code}/{path}', [PluginController::class, 'asset'])->where('path', '(.*)')->name('plugin.asset'); + Route::post('inquiry', [InquiryController::class, 'store'])->name('brands.index'); + Route::middleware('checkout_auth:' . Customer::AUTH_GUARD) ->group(function () { Route::get('carts', [CartController::class, 'index'])->name('carts.index'); diff --git a/beike/Shop/Services/InquiryService.php b/beike/Shop/Services/InquiryService.php new file mode 100644 index 00000000..5f1ce747 --- /dev/null +++ b/beike/Shop/Services/InquiryService.php @@ -0,0 +1,24 @@ + + * @created 2022-06-30 19:37:05 + * @modified 2022-06-30 19:37:05 + */ + +namespace Beike\Shop\Services; + +use Beike\Repositories\InquiryRepo; + +class InquiryService +{ + public static function create($data) + { + $inquiry = InquiryRepo::create($data); + + return $inquiry; + } +} diff --git a/package-lock.json b/package-lock.json index 7c2ed717..dd395498 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2097,6 +2097,14 @@ "integrity": "sha512-p4jj6Fws4Iy2m0iCmI2am2ZNZCgbdgE+P8F/8csmn2vx7ixXrO2zGcuNsD46X5uZSVecmkEy/M06X2vG8KD6dQ==", "dev": true }, + "async-validator": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-1.8.5.tgz", + "integrity": "sha512-tXBM+1m056MAX0E8TL2iCjg8WvSyXu0Zc8LNtYqrVeyoL3+esHRZ4SieE9fKQyyU09uONjnMEjrNBMqT0mbvmA==", + "requires": { + "babel-runtime": "6.x" + } + }, "autoprefixer": { "version": "10.4.14", "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz", @@ -2120,6 +2128,11 @@ "follow-redirects": "^1.14.0" } }, + "babel-helper-vue-jsx-merge-props": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz", + "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==" + }, "babel-loader": { "version": "8.3.0", "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.3.0.tgz", @@ -2170,6 +2183,22 @@ "@babel/helper-define-polyfill-provider": "^0.4.0" } }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + }, + "dependencies": { + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + } + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -2874,6 +2903,11 @@ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "dev": true }, + "core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==" + }, "core-js-compat": { "version": "3.30.2", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.30.2.tgz", @@ -3137,6 +3171,11 @@ "ms": "2.1.2" } }, + "deepmerge": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz", + "integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==" + }, "default-gateway": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz", @@ -3324,6 +3363,19 @@ "integrity": "sha512-5VXLW4Qw89vM2WTICHua/y8v7fKGDRVa2VPOtBB9IpLvW316B+xd8yD1wTmLPY2ot/00P/qt87xdolj4aG/Lzg==", "dev": true }, + "element-ui": { + "version": "2.15.13", + "resolved": "https://registry.npmjs.org/element-ui/-/element-ui-2.15.13.tgz", + "integrity": "sha512-LJoatEYX6WV74FqXBss8Xfho9fh9rjDSzrDrTyREdGb1h1R3uRvmLh5jqp2JU137aj4/BgqA3K06RQpQBX33Bg==", + "requires": { + "async-validator": "~1.8.1", + "babel-helper-vue-jsx-merge-props": "^2.0.0", + "deepmerge": "^1.2.0", + "normalize-wheel": "^1.0.1", + "resize-observer-polyfill": "^1.5.0", + "throttle-debounce": "^1.0.1" + } + }, "elliptic": { "version": "6.5.4", "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.4.tgz", @@ -5151,6 +5203,11 @@ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true }, + "normalize-wheel": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/normalize-wheel/-/normalize-wheel-1.0.1.tgz", + "integrity": "sha512-1OnlAPZ3zgrk8B91HyRj+eVv+kS5u+Z0SCsak6Xil/kmgEia50ga7zfkumayonZrImffAxPU/5WcyGhzetHNPA==" + }, "npm-run-path": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", @@ -6059,6 +6116,11 @@ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", "dev": true }, + "resize-observer-polyfill": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz", + "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg==" + }, "resolve": { "version": "1.22.2", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.2.tgz", @@ -6865,6 +6927,11 @@ } } }, + "throttle-debounce": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/throttle-debounce/-/throttle-debounce-1.1.0.tgz", + "integrity": "sha512-XH8UiPCQcWNuk2LYePibW/4qL97+ZQ1AN3FNXwZRBNPPowo/NRU5fAlDCSNBJIYCKbioZfuYtMhG4quqoJhVzg==" + }, "thunky": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz", diff --git a/package.json b/package.json index 1d81b15e..680bfade 100644 --- a/package.json +++ b/package.json @@ -20,5 +20,8 @@ "resolve-url-loader": "^4.0.0", "sass": "^1.38.1", "sass-loader": "^12.1.0" + }, + "dependencies": { + "element-ui": "^2.15.13" } } diff --git a/public/build/beike/shop/default/js/app.js b/public/build/beike/shop/default/js/app.js index 863eb7b1..303d6c09 100644 --- a/public/build/beike/shop/default/js/app.js +++ b/public/build/beike/shop/default/js/app.js @@ -2332,6 +2332,10 @@ $(function () { }); }); function updateMiniCartData(res) { + var cart_item_price = $('.offcanvas-right-cart-item-price'); + for (var i = 0; i < cart_item_price.length; i++) { + cart_item_price.contents()[i].nodeValue = ' ' + res.data.carts[i].price_format + ' x '; + } $('.offcanvas-right-cart-count').text(res.data.quantity); $('.offcanvas-right-cart-amount').text(res.data.amount_format); } diff --git a/resources/beike/admin/views/pages/inquiry/form.blade.php b/resources/beike/admin/views/pages/inquiry/form.blade.php new file mode 100644 index 00000000..6c60e6b6 --- /dev/null +++ b/resources/beike/admin/views/pages/inquiry/form.blade.php @@ -0,0 +1,212 @@ +@extends('admin::layouts.master') + +@section('title', __('admin/page.index')) + +@section('body-class', 'page-pages-form') + +@push('header') + + + +@endpush + +@section('page-title-right') + + + +@endsection + +@section('content') + + + +
+
+
+
+
+ @csrf + @method($page->id ? 'PUT' : 'POST') + +
+ @foreach (locales() as $language) +
+ @php + $error_title = $errors->first("descriptions.{$language['code']}.title"); + @endphp + + + +
+ +
+
+ + +
+ +
+ @if ($errors->has("descriptions.{$language['code']}.content")) + {{ $errors->first("descriptions.{$language['code']}.content") }} + @endif +
+ + + + + +
+ @endforeach +
+
+
+ @hook('admin.page.data.before') + + + +
+ + +
+
+ + + +
+
+ + +
+ + +
+
+
+
+ + @hook('admin.page.data.after') + + +
+
+ + +
+
+
+ + @hook('admin.page.form.footer') +@endsection + +@push('footer') + +@endpush + + + diff --git a/resources/beike/admin/views/pages/inquiry/index.blade.php b/resources/beike/admin/views/pages/inquiry/index.blade.php new file mode 100644 index 00000000..c75f330a --- /dev/null +++ b/resources/beike/admin/views/pages/inquiry/index.blade.php @@ -0,0 +1,97 @@ +@extends('admin::layouts.master') + +@section('title', __('admin/page.inquiry')) + +@section('content') + + @if ($errors->has('error')) + + @endif + +
+
+{{--
--}} +{{-- {{ __('common.add') }}--}} +{{--
--}} +
+ + + + + + + + + + + @hook('admin.page.list.column') + + + + + @if (count($pages_format)) + @foreach ($pages_format as $page) + + + + +{{-- --}} + + + + + @hook('admin.page.list.column_value') + + + @endforeach + @else + + @endif + +
ID{{ __('common.sku') }}{{ __('common.contacts') }}{{ __('common.email') }}{{ __('common.content') }}{{ __('common.created_at') }}{{ __('common.updated_at') }}{{ __('common.action') }}
{{ $page['id'] }} +
{{ $page['product_sku_sku'] ?? '' }}
+
+
{{ $page['contacts'] ?? '' }}
+
--}} +{{-- {{ $page['active'] ? __('common.enable') : __('common.disable') }}--}} +{{-- +
{{ $page['email'] ?? '' }}
+
+
{{ $page['content'] ?? '' }}
+
{{ $page['created_at'] }}{{ $page['updated_at'] }} +{{-- {{ __('common.edit') }}--}} + + @hook('admin.page.list.action') +
+
+ + {{ $pages->links('admin::vendor/pagination/bootstrap-4') }} + +
+
+ + @hook('admin.page.list.content.footer') +@endsection + +@push('footer') + +@endpush diff --git a/resources/beike/admin/views/pages/products/form/form.blade.php b/resources/beike/admin/views/pages/products/form/form.blade.php index a5336d79..53ab454c 100644 --- a/resources/beike/admin/views/pages/products/form/form.blade.php +++ b/resources/beike/admin/views/pages/products/form/form.blade.php @@ -107,12 +107,26 @@
{{ __('admin/product.stocks') }}
- - + +
+
+ price_setting == 'sku' ? 'checked' : '' }}> + +
+
+ price_setting == 'num' ? 'checked' : '' }}> + +
+
+ + + + +
@@ -277,6 +291,68 @@ + + + +{{-- 阶梯价格设置表格 (最小起订量,产品价格),预览,可以增加删除价格区间--}} +
+
+
+
最小起订量
+
产品价格
+
删除
+
+
+
+
+
+
+ +
+
_@{{ item.num }}件
+
+
+ +
@{{ item.num }}件等于价格:@{{ item.num * item.price }}
+
+ +
+
+ +
+
+
+ 预览 +
+
+
+
@{{ item.num }} ~ @{{ form.numPrices[index + 1].num - 1 }}
+
≧@{{ item.num }}
+
价格@{{ item.price }}
+
+
+
+
+ + +
新增价格区间
+ +
@@ -490,6 +566,8 @@ status: @json($product->skus[0]['status'] ?? false), variables: @json($product->variables ?? []), skus: @json(old('skus', $product->skus) ?? []), + price_setting: @json(old('price_setting', $product->price_setting) ?? 'sku'), + numPrices: @json(old('numPrices', $product->numprices) ?? []), }, variablesBatch: { @@ -555,6 +633,10 @@ skuIsEmpty() { return (this.form.skus.length && this.form.skus[0].variants.length) || '' + }, + + numPricesIsEmpty() { + return (this.form.numPrices.length && this.form.price_setting === 'num') || this.form.price_setting === 'sku' || '' } }, @@ -589,10 +671,24 @@ } }, + created() { + if(this.form.numPrices.length === 0){ + this.addNumPrices(); + } + }, + methods: { + addNumPrices() { + this.form.numPrices.push({num: '', price: ''}); + }, + + removeNumPrices(index) { + this.form.numPrices.splice(index, 1) + }, + // 表单提交,检测是否开启多规格 做处理 productsSubmit() { - if (!this.editing.isVariable) { + if (!this.editing.isVariable || this.form.price_setting === 'num') { this.source.variables = []; } }, @@ -948,5 +1044,104 @@ } }); }); - + + @endpush diff --git a/resources/beike/shop/default/js/header.js b/resources/beike/shop/default/js/header.js index 3b2d161d..6596b93a 100644 --- a/resources/beike/shop/default/js/header.js +++ b/resources/beike/shop/default/js/header.js @@ -71,6 +71,10 @@ $(function () { }) function updateMiniCartData(res) { + let cart_item_price = $('.offcanvas-right-cart-item-price'); + for(var i = 0 ; i< cart_item_price.length ;i++){ + cart_item_price.contents()[i].nodeValue =' ' + res.data.carts[i].price_format + ' x '; + } $('.offcanvas-right-cart-count').text(res.data.quantity); $('.offcanvas-right-cart-amount').text(res.data.amount_format); } diff --git a/resources/lang/en/admin/page.php b/resources/lang/en/admin/page.php index 9c49a7b5..8b54ad96 100644 --- a/resources/lang/en/admin/page.php +++ b/resources/lang/en/admin/page.php @@ -19,4 +19,5 @@ return [ 'pages_show' => 'Detail', 'pages_update' => 'Edit', 'pages_delete' => 'Delete', + 'inquiry' => 'Inquiry', ]; diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index 08b045b5..89be5081 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -86,6 +86,10 @@ return [ 'error_page' => 'The data you accessed does not exist or has been deleted~', 'error_page_btn' => 'Return to previous page', + 'contacts' => 'Contacts', + 'content' => 'Content', + 'sku' => 'Sku', + 'order' => [ 'unpaid' => 'Unpaid', 'paid' => 'Paid', diff --git a/resources/lang/en/shop/products.php b/resources/lang/en/shop/products.php index 5ce52a43..e20985bf 100644 --- a/resources/lang/en/shop/products.php +++ b/resources/lang/en/shop/products.php @@ -18,4 +18,9 @@ return [ 'in_stock' => 'In Stock', 'out_stock' => 'Out Stock', 'model' => 'Model', + 'quantity_error' => 'Quantity Error', + 'inquiry' => 'Inquiry', + 'enter_contacts' => 'Please enter contacts', + 'enter_email' => 'Please enter email', + 'enter_content' => 'Please enter content', ]; diff --git a/resources/lang/zh_cn/admin/page.php b/resources/lang/zh_cn/admin/page.php index 208e2667..fbd2f4a5 100644 --- a/resources/lang/zh_cn/admin/page.php +++ b/resources/lang/zh_cn/admin/page.php @@ -19,4 +19,6 @@ return [ 'pages_show' => '文章详情', 'pages_update' => '文章编辑', 'pages_delete' => '删除文章', + + 'inquiry' => '询盘管理', ]; diff --git a/resources/lang/zh_cn/admin/product.php b/resources/lang/zh_cn/admin/product.php index ee5a4af8..bfc2bde4 100644 --- a/resources/lang/zh_cn/admin/product.php +++ b/resources/lang/zh_cn/admin/product.php @@ -31,7 +31,7 @@ return [ 'price' => '价格', 'origin_price' => '原价', 'cost_price' => '成本价', - 'quantity' => '数量', + 'quantity' => '库存数量', 'enable_multi_spec' => '启用多规格', 'image_help' => '第一张图片将作为商品主图,支持同时上传多张图片,多张图片之间可随意调整位置', 'add_variable' => '添加规格', @@ -44,4 +44,9 @@ return [ 'confirm_batch_status' => '确认要批量修改选中的商品的状态吗?', 'confirm_batch_restore' => '确认要恢复选中的商品吗?', 'confirm_delete_restore' => '确认要清空回收站吗?', + 'price_setting' => '价格设置', + 'price_setting_by' =>[ + 'sku' => '根据规格设置价格', + 'num' => '根据数量设置价格', + ] ]; diff --git a/resources/lang/zh_cn/common.php b/resources/lang/zh_cn/common.php index b6711bfd..3c844907 100644 --- a/resources/lang/zh_cn/common.php +++ b/resources/lang/zh_cn/common.php @@ -85,6 +85,11 @@ return [ 'error_page' => '您访问的数据不存在或已被删除~', 'error_page_btn' => '返回上一页', + 'contacts' => '联系人', + 'content' => '内容', + 'sku' => 'Sku', + + 'order' => [ 'unpaid' => '待支付', 'paid' => '已支付', diff --git a/resources/lang/zh_cn/shop/products.php b/resources/lang/zh_cn/shop/products.php index 180e9a66..d67a7a3b 100644 --- a/resources/lang/zh_cn/shop/products.php +++ b/resources/lang/zh_cn/shop/products.php @@ -18,4 +18,9 @@ return [ 'in_stock' => '有货', 'out_stock' => '缺货', 'model' => '型号', + 'quantity_error' => '数量错误', + 'inquiry' => '咨询', + 'enter_contacts' => '请输入联系人', + 'enter_email' => '请输入邮件', + 'enter_content' => '请输入内容', ]; diff --git a/themes/default/cart/mini.blade.php b/themes/default/cart/mini.blade.php index 49ce6670..28fb9737 100644 --- a/themes/default/cart/mini.blade.php +++ b/themes/default/cart/mini.blade.php @@ -13,13 +13,13 @@
-
+
{{ $cart['name'] }}
{{ $cart['variant_labels'] }}
-
+
{{ $cart['price_format'] }} x diff --git a/themes/default/product.blade.php b/themes/default/product.blade.php index e947f317..be768994 100644 --- a/themes/default/product.blade.php +++ b/themes/default/product.blade.php @@ -9,6 +9,10 @@ + + + + @endpush @section('content') @@ -55,12 +59,33 @@ @hookwrapper('product.detail.name')

{{ $product['name'] }}

@endhookwrapper -
-
@{{ product.price_format }}@{{ price_setting }}
+
+
@{{ product.price_format }}
@{{ product.origin_price_format }}
+
+
+
@{{ item.num }} - @{{ numPrices[index + 1].num - 1 }} sets
+ +
>= @{{ item.num }} sets
+
+
@{{ item.price_format }}
+
+
+
@hookwrapper('product.detail.quantity')
@@ -139,6 +164,12 @@ @click="addCart(true, this)" >{{ __('shop/products.buy_now') }} + @hook('product.detail.buy.after')
@@ -152,7 +183,42 @@
- + + + + + + + + +{{-- --}} +{{-- --}} +{{-- --}} +{{-- --}} +{{-- 组合--}} +{{-- 不明--}} +{{-- --}} +{{-- --}} + + +{{-- --}} +{{-- --}} +{{-- --}} + + + + + + + + + +{{-- Cancel--}} + Submit + +