| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316 |
- <template>
- <Theme>
- <view class="wrap">
- <Navbar title="运费估算" fixed border> </Navbar>
- <view class="container">
- <view class="card">
- <view class="field">
- <trans class="label required" _t="从VAVABUY到"></trans>
- <UPickerField
- v-model="form.country"
- :columns="cityOptions"
- labelKey="name"
- valueKey="id"
- @change="onCityChange"
- />
- </view>
- <!-- 重量 -->
- <view class="field">
- <view class="label required">
- <trans _t="重量(克)" />
- </view>
- <Search
- class="input"
- type="number"
- border="none"
- inputAlign="right"
- :placeholder="t('请输入重量')"
- v-model.trim="form.weight"
- />
- </view>
- <!-- 商品类别 折叠 -->
- <view class="collapse">
- <view class="collapse-head" @tap="toggleCate">
- <trans _t="商品类别" />
- <MultiSelectDropdown
- v-model="selectedIds"
- :placeholder="t('请选择商品类别')"
- :options="categoryOptions"
- @change="handleChange"
- />
- </view>
- </view>
- <!-- 体积输入 -->
- <view class="dim-list">
- <view class="dim-item" v-for="item in dims" :key="item.key">
- <view class="dim-label">{{ t(item.label) }}</view>
- <view class="dim-input-wrap">
- <Search
- class="dim-input"
- type="number"
- border="none"
- inputAlign="right"
- v-model.trim="form[item.key]"
- />
- <text class="unit">cm</text>
- </view>
- </view>
- </view>
- </view>
- <!-- 底部按钮 -->
- <view class="footer">
- <button class="btn" type="default" @tap="submit">
- <trans _t="查询" />
- </button>
- </view>
- </view>
- <view class="result">
- <view class="list" v-for="(item, index) in detail" :key="index">
- <logisticsList :item="item" />
- </view>
- </view>
- </view>
- </Theme>
- </template>
- <script setup>
- import { reactive, ref, nextTick } from "vue";
- import Navbar from "@/components/navbar";
- import navMenu from "@/components/nav_menu";
- import Search from "@/components/input";
- import UPickerField from "@/components/UPickerField.vue";
- import MultiSelectDropdown from "@/components/MultiSelectDropdown.vue";
- import logisticsList from "./components/logistics_list";
- import { t } from "@/locale";
- import { SHOP_EXPRESS_CONFIG, SHOP_POST_CALCULATE } from "@/api";
- import { onShow } from "@dcloudio/uni-app";
- import { Toast } from "@/utils";
- const detail = ref([]);
- const form = reactive({
- weight: "", // g
- length: "", // cm
- width: "",
- height: "",
- category: "",
- country: "",
- });
- const dims = [
- { key: "length", label: "长度" },
- { key: "width", label: "宽度" },
- { key: "height", label: "高度" },
- ];
- const cityOptions = ref([]);
- const onCityChange = (e) => {
- console.log("change:", e);
- };
- const categoryOptions = ref([]);
- // 选中的ID
- const selectedIds = ref([]);
- const handleChange = (data) => {
- form.category = data.ids.join(",");
- };
- const submit = async () => {
- if (!form.country || !form.weight) {
- return Toast(t("请填写必填信息"));
- }
- try {
- detail.value = [];
- const res = await SHOP_POST_CALCULATE(form);
- detail.value = res.data;
- } catch (error) {
- Toast(error.msg);
- }
- };
- const getConfig = async () => {
- try {
- const res = await SHOP_EXPRESS_CONFIG();
- categoryOptions.value = res.data.category || [];
- cityOptions.value = res.data.counrty || [];
- } catch (error) {
- Toast(error.msg);
- }
- };
- onShow(() => {
- nextTick(() => {
- getConfig();
- });
- });
- </script>
- <style lang="less" scoped>
- @import url("@/style.less");
- .wrap {
- min-height: 100vh;
- background-color: var(--bg);
- .container {
- padding: 24rpx;
- .field {
- min-height: 100rpx;
- display: flex;
- justify-content: space-between;
- border: 1rpx solid var(--borderColor);
- border-radius: 18rpx;
- padding: 16rpx 24rpx;
- align-items: center;
- margin-bottom: 24rpx;
- .label {
- color: var(--black);
- font-weight: 600;
- .size(26rpx);
- &.required::before {
- content: "*";
- color: #ff4d4f;
- font-weight: 600;
- .size(18rpx);
- margin-right: 4rpx;
- }
- &.to {
- justify-self: center;
- color: var(--bor-color1);
- font-weight: 500;
- }
- }
- .picker {
- display: flex;
- align-items: center;
- justify-content: space-between;
- gap: 8rpx;
- padding: 6rpx 0;
- &.picker-full {
- width: 100%;
- }
- }
- .primary {
- color: #0ea5e9;
- font-weight: 700;
- }
- .muted {
- color: var(--black);
- }
- .arrow {
- color: var(--black);
- font-weight: 600;
- .size(32rpx);
- transform: translateY(-1rpx);
- &.open {
- transform: rotate(180deg) translateY(1rpx);
- }
- &.small {
- font-size: 16rpx;
- }
- }
- .input {
- background: transparent;
- }
- }
- /* 折叠块 */
- .collapse {
- border: 1px solid var(--borderColor);
- border-radius: 12px;
- margin-bottom: 12px;
- .collapse-head {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 12px;
- color: var(--black);
- font-weight: 600;
- .size(26rpx);
- }
- .collapse-body {
- padding: 0 12px 12px;
- }
- }
- /* 尺寸输入 */
- .dim-list {
- background: #fff;
- border-radius: 12px;
- overflow: hidden;
- border: 1px solid var(--borderColor);
- .dim-item {
- display: flex;
- align-items: center;
- justify-content: space-between;
- padding: 14px 12px;
- border-bottom: 1px solid var(--borderColor);
- &:last-child {
- border-bottom: 0;
- }
- }
- .dim-label {
- .size(24rpx);
- font-weight: 600;
- color: var(--black);
- }
- .dim-input-wrap {
- display: flex;
- align-items: center;
- gap: 16rpx;
- .dim-input {
- min-width: 120rpx;
- background: transparent;
- }
- .unit {
- color: var(--bor-color1);
- }
- }
- }
- /* 底部按钮 */
- .footer {
- position: sticky;
- bottom: 0;
- margin-top: 16px;
- padding: 10px 0 6px;
- background: linear-gradient(
- to bottom,
- rgba(255, 255, 255, 0),
- #fff 30%,
- #fff
- );
- .btn {
- width: 100%;
- height: 44px;
- line-height: 44px;
- border-radius: 10px;
- color: #fff;
- background: var(--black);
- font-weight: 700;
- border: none;
- &:active {
- opacity: 0.9;
- }
- }
- }
- }
- .result {
- padding: 24rpx;
- .list {
- width: 100%;
- }
- }
- }
- </style>
|